提取器( Extractors)
Scala中的提取器是一个对象,它有一个名为unapply的方法作为其成员之一。 该unapply方法的目的是匹配一个值并将其分开。 通常,提取器对象还定义了apply构建值的双重方法,但这不是必需的。
例子 (Example)
让我们举一个对象定义apply和unapply方法的例子。 apply方法具有与以往相同的含义:它将Test转换为可以应用于括号中的参数的对象,方法与应用方法相同。 所以你可以编写Test(“Zara”,“gmail.com”)来构造字符串“Zara@gmail.com”。
unapply方法是将Test类转换为extractor ,它反转了apply的构造过程。 如果apply需要两个字符串并形成一个电子邮件地址字符串,则unapply将获取一个电子邮件地址并返回两个字符串: user和地址domain 。
unapply还必须处理给定字符串不是电子邮件地址的情况。 这就是为什么unapply在字符串对上返回Option类型的原因。 如果字符串str是具有给定用户和域部分的电子邮件地址,则其结果是Some (user, domain) ;如果str不是电子邮件地址,则结果为None。 以下是一些示例。
语法 (Syntax)
unapply("Zara@gmail.com") equals Some("Zara", "gmail.com")
unapply("Zara Ali") equals None
以下示例程序显示了电子邮件地址的提取器对象。
例子 (Example)
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 。 以下命令用于编译和执行此程序。
Command
\>scalac Demo.scala
\>scala Demo
输出 (Output)
Apply method : Zara@gmail.com
Unapply method : Some((Zara,gmail.com))
Unapply method : None
与提取器匹配的模式
当类的实例后跟带有零个或多个参数列表的括号时,编译器apply在该实例上调用apply方法。 我们可以在对象和类中定义应用。
如上所述, unapply方法的目的是提取我们正在寻找的特定值。 它做相反的操作apply 。 使用match语句比较提取器对象时,将自动执行unapply方法。
请尝试以下示例程序。
例子 (Example)
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 。 以下命令用于编译和执行此程序。
Command
\>scalac Demo.scala
\>scala Demo
输出 (Output)
10
10 is bigger two times than 5