Extractor Object是有unapply
方法的对象。apply
方法像是构造函数,可以带参数以及创建对象,unapply
方法根据对象尝试返回其参数。常用于模式匹配和partial functions。
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("Sukyoung")
时,相当于调用CustomerID.apply("Sukyoung")
。当调用case CustomerID(name) => customer1ID
时,相当于调用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的一个sub-value,则返回Option[T]。
- 如果想要返回多个sub-value T1,...,Tn,使用元组组织Option[(T1,...,Tn)]。
有时,sub-value的数量是固定的并且想要返回一个序列。为此,也可以通过unapplySeq
定义模式,返回Option[Seq[T]]。这个机制用于匹配模式case List(x1, ..., xn)
。