提取器对象是一个具有 unapply
方法的对象。而 apply
方法类似于一个构造函数,它接收参数并创建一个对象,unapply
接收一个对象并尝试返回参数。这通常用于模式匹配和部分函数。
import scala.util.Random
object CustomerID {
def apply(name: String) = s"$name--${Random.nextLong()}"
def unapply(customerID: String): Option[String] = {
val stringArray: Array[String] = customerID.split("--")
if (stringArray.tail.nonEmpty) Some(stringArray.head) else None
}
}
val customer1ID = CustomerID("Sukyoung") // Sukyoung--23098234908
customer1ID match {
case CustomerID(name) => println(name) // prints Sukyoung
case _ => println("Could not extract a CustomerID")
}
import scala.util.Random
object CustomerID:
def apply(name: String) = s"$name--${Random.nextLong()}"
def unapply(customerID: String): Option[String] =
val stringArray: Array[String] = customerID.split("--")
if stringArray.tail.nonEmpty then Some(stringArray.head) 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) => println(name)
时,我们使用 CustomerID.unapply(customer1ID)
调用 unapply 方法。
由于值定义可以使用模式来引入新变量,因此可以使用提取器来初始化变量,其中 unapply 方法提供值。
val customer2ID = CustomerID("Nico")
val CustomerID(name) = customer2ID
println(name) // prints Nico
这等效于 val name = CustomerID.unapply(customer2ID).get
。
val CustomerID(name2) = "--asdfasdfasdf"
如果没有匹配项,则会抛出 scala.MatchError
val CustomerID(name3) = "-asdfasdfasdf"
unapply
的返回类型应按如下方式选择
- 如果仅仅是一个测试,返回
Boolean
。例如case even()
。 - 如果返回类型 T 的单个子值,返回
Option[T]
。 - 如果您想返回多个子值
T1,...,Tn
,将它们分组到可选元组Option[(T1,...,Tn)]
中。
有时,要提取的值的数量不是固定的,我们希望根据输入返回任意数量的值。对于此用例,您可以使用 unapplySeq
方法定义提取器,该方法返回 Option[Seq[T]]
。这些模式的常见示例包括使用 case List(x, y, z) =>
解构 List
,以及使用正则表达式 Regex
分解 String
,例如 case r(name, remainingFields @ _*) =>
。