解析器对象一个拥有 unapply
方法的对象。正如 apply
方法像一个构造器一样将参数加工成一个对象,unapply
方法将一个对象解析并返回参数。这经常用于模式匹配和局部函数。
import scala.util.Random
object CustomerID {
def apply(name: String) = s"$name--${Random.nextLong}"
def unapply(customerID: String): Option[String] = {
val name = customerID.split("--").head
if (name.nonEmpty) Some(name) else None
}
}
val customer1ID = CustomerID("Sukyoung") // Sukyoung--23098234908
customer1ID match {
case CustomerID(name) => println(name) // prints Sukyoung
case _ => println("Could not extract a CustomerID")
}
apply
方法使用一个 name
参数,创建了一个 CustomerID
字符串。而 unapply
方法则反向得到 name
参数。当我们调用 CustomerID("Suyoung")
时,其实调用的是 CustomerID.apply("Suyoung")
,这是一种简写语法。同理,当我们调用 case CustomerID(name) => println(name)
,我们调用的是 unapply
方法。
unapply
方法也可以被用来赋值。
val customer2ID = CustomerID("Nico")
val CustomerID(name) = customer2ID
println(name) // prints Nico
上面的代码等同于 val name = CustomerID.unapply(customer2ID).get
。如果没有匹配,抛出一个 scala.MatchError
错误。
val CustomerID(name2) = "--asdfasdfasdf"
unapply
方法的返回值类型应是以下几种类型:
如果仅仅是测试是否匹配一个对象,返回
Boolean
类型。例如:case even()
。如果返回一个类型为 T 的参数,返回一个
Option[T]
。如果你想返回多个参数
T1,...,Tn
,将它们放入一个可选元组中Option[(T1,...,Tn)]
返回(对比上一条,T1,...,Tn
应该是参数的类型才对,原文是意思T1,...,Tn
好像是参数值)。
有时,返回的参数的个数不是固定的,我们就需要返回一个序列。因为这个原因,你必须定义一个 unapplySeq
方法来返回 Option[Seq[T]]
。这种机制被用来匹配 case List(x1, ..., xn)
。