Source From Here
不同個數的元素提取
unapply() 方法可以僅提取一個結果,例如:
或是傳回
Boolean 型態,表示模式比對是否成功,可以運用這個特性,改寫上面找出住在高雄的學生姓名之範例:
注意上例中,模式比對時
Kaohsiung() 的括號是必要的,這用以區別要使用 Kaohsiung 的 unapply() 方法而不是 Kaohsiung 物件。這個例子也示範了使用提取器進行模式比對的一個好處,你可以連續提取,上例中,先使用 Student 提取器提取出 name 與 addr,再進一步使用 Kaohsiung() 提取器判斷 addr 模式比對是否成功。
如果事先無法知道提取方法會提取出的元素個數,則無法使用 unapply() 方法 來定義提取的動作,例如,也許使用者會輸入一串文字,當中包括大小寫字母,你想要提取出其中大寫字母,但問題是使用者輸入的文字長度是無法預測的,自然也就無法預測所提取的大寫字母不個數會有多少。若想要提取的元素個數不定,則可以定義 unapplySeq() 方法,例如:
你在 List 模式 中看到的比對方式,都可以套用在上例的提取器中,例如:
事實上,
List 正是實作了 unapplySeq() 方法,才可以使用 List 模式 中所看到的比對模式。unapplySeq() 方法也可以選擇性的傳回固定個數的元素之後,再提供未定個數的元素部份,例如下例找出使用者名稱為 "caterpillar" 的郵件,取得其網域切割後的字串陣列:
不同個數的元素提取
unapply() 方法可以僅提取一個結果,例如:
- object Address {
- def unapply(str: String): Option[String] = {
- val data = str.split(",")
- if (data.length == 3) Some(data(2)) else None
- }
- }
- val Address(addr) = "B123456,Justin,Kaohsiung"
- println(addr) // Kaohsiung
- object Student {
- def unapply(str: String) = {
- val data = str.split(",")
- if (data.length == 3) Some(data(0), data(1), data(2)) else None
- }
- }
- object Kaohsiung {
- def unapply(str: String): Boolean = str == "Kaohsiung"
- }
- val students = List(
- "B123456,Justin,Kaohsiung",
- "B98765,Monica,Kaohsiung",
- "B246819,Bush,Taipei"
- )
- students.foreach(_ match {
- case Student(_, name, addr @ Kaohsiung()) => println(name)
- case _ =>
- })
如果事先無法知道提取方法會提取出的元素個數,則無法使用 unapply() 方法 來定義提取的動作,例如,也許使用者會輸入一串文字,當中包括大小寫字母,你想要提取出其中大寫字母,但問題是使用者輸入的文字長度是無法預測的,自然也就無法預測所提取的大寫字母不個數會有多少。若想要提取的元素個數不定,則可以定義 unapplySeq() 方法,例如:
你在 List 模式 中看到的比對方式,都可以套用在上例的提取器中,例如:
- val strs = Array(
- "Scala is Java?",
- "Java is Scala?",
- "Java 7 will include closure!",
- "Scala already has closure.")
- strs.foreach(_ match {
- case Uppercase('J') => println("only 'J' mentioned")
- case Uppercase('J', 'S') => println("'JS' mentioned")
- case other => println("other: " + other)
- })
- object Email {
- def unapplySeq(s: String): Option[(String, Seq[String])] = {
- val parts = s.split("@")
- if(parts.length == 2) Some((parts(0), parts(1).split("\\.")))
- else None
- }
- }
- val strs = Array(
- "caterpillar@gmail.com",
- "caterpillar@openhome.cc",
- "Justin@openhome.cc")
- strs.foreach(_ match {
- case Email("caterpillar", domain @ _*) => println(domain)
- case _ =>
- })
沒有留言:
張貼留言