Scala 抽取器
Scala中的抽取器是一个对象,其中有一个被称为 unapply 的方法。该unapply方法的目的是匹配一个值并将其拆分。通常,抽取器对象还定义了一个双向方法 apply 用于构建值,但这并非必需。
示例
让我们以一个定义了 apply 和 unapply 方法的对象为例。apply方法的意义与以往相同:它将Test转换为一个可以像方法一样应用于括号中的参数的对象。因此,您可以编写Test(“Zara”, “gmail.com”)来构造字符串”Zara@gmail.com”。
unapply 方法将Test类转换为一个 抽取器 ,它颠倒了 apply 的构造过程。其中,apply接受两个字符串并将它们组成一个电子邮件地址字符串,而unapply接受一个电子邮件地址并返回可能是两个字符串的结果:用户和地址的域名。
unapply 还必须处理给定字符串不是电子邮件地址的情况。这就是为什么unapply返回一个Option类型的字符串对。如果字符串str是具有给定用户和域名部分的电子邮件地址,则结果为 Some(user, domain) ,如果str不是电子邮件地址,则结果为None。以下是一些示例。
语法
unapply("Zara@gmail.com") equals Some("Zara", "gmail.com")
unapply("Zara Ali") equals None
以下示例程序显示了一个用于提取电子邮件地址的提取器对象。
示例
object Demo {
def main(args: Array[String]) {
println ("Apply method : " + apply("Zara", "gmail.com"));
println ("Unapply method : " + unapply("Zara@gmail.com"));
println ("Unapply method : " + unapply("Zara Ali"));
}
// The injection method (optional)
def apply(user: String, domain: String) = {
user +"@"+ domain
}
// The extraction method (mandatory)
def unapply(str: String): Option[(String, String)] = {
val parts = str split "@"
if (parts.length == 2){
Some(parts(0), parts(1))
} else {
None
}
}
}
将上述程序保存在 Demo.scala 中。使用以下命令来编译和执行此程序。
命令
>scalac Demo.scala
\>scala Demo
输出
Apply method : Zara@gmail.com
Unapply method : Some((Zara,gmail.com))
Unapply method : None
使用提取器进行模式匹配
当一个类的实例后跟着括号,括号内有零个或多个参数列表时,编译器会调用该实例上的 apply 方法。我们可以在对象和类中都定义 apply 方法。
如上所述, unapply 方法的目的是提取我们要查找的特定值。它执行与 apply 方法相反的操作。当使用 match 语句来比较一个提取器对象时, unapply 方法将被自动执行。
请尝试以下示例程序。
示例
object Demo {
def main(args: Array[String]) {
val x = Demo(5)
println(x)
x match {
case Demo(num) => println(x+" is bigger two times than "+num)
//unapply is invoked
case _ => println("i cannot calculate")
}
}
def apply(x: Int) = x*2
def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None
}
将上述程序保存在 Demo.scala 文件中。以下命令用于编译和执行此程序。
命令
>scalac Demo.scala
\>scala Demo
输出
10
10 is bigger two times than 5