萃取器物件是一個具有 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
,請將它們分組在一個選用 tupleOption[(T1,...,Tn)]
中。
有時,要萃取的值的數量並非固定,我們希望根據輸入回傳任意數量的值。對於此使用案例,您可以使用具有 unapplySeq 方法的萃取器,該方法會回傳 Option[Seq[T]]
。這些樣式的常見範例包括使用 case List(x, y, z) =>
解構 List
,以及使用正規表示法 Regex
分解 String
,例如 case r(name, remainingFields @ _*) =>
。