2016-12-26 155 views
1

我想了解scala unapply方法。斯卡拉unapply方法

以下是我的理解。說,如果我有一個Person對象:

class Person(val fname: String, val lname: String) 

object Person{ 
    def unapply(x: Person) : Option[(String, String)] = 
    Some(x.fname,x.lname) 
} 

new Person("Magic", "Mike") match { 
    case Person(x, y) => s"Last Name is ${y}" 
    case _ => "Unknown" 
} 

這我相信的情況下要求是這樣的:

val temp = Person.unapply(new Person("Magic", "Mike")) 
if (temp != None) { val (x, y) = temp.get } 
else { <go to next case> } 

但如何做以下不應用工作的時候,我有如下圖所示:

new Person("Magic", "Mike") match { 
    case Person("Harold", y) => s"Last Name is ${y}" 
    case Person("Magic", y) => s"Last Name is ${y}" 
    case _ => "Unknown" 
} 

它如何在不適用的方法中訪問fname(「Magic」)的值,並給出與第一個相同/正確的結果?

+0

這很神奇!說真的,在哪裏沒有太多的關於「它是如何工作的」。 Scala編譯器將'Person(foo,bar)'看作'Person(foo,bar)',並用適當的參數調用Person.unapply來替換它,檢查返回值,並將值賦給提供的變量或將它們與給定的常量進行匹配。 – Dima

回答

3

運行scalac-Xprint:patmat會告訴你的樹如何句法模式匹配階段之後看:

scalac -Xprint:patmat test.scala 

    case <synthetic> val x1: Person = new Person("Magic", "Mike"); 
    case10(){ 
    <synthetic> val o12: Option[(String, String)] = Person.unapply(x1); 
    if (o12.isEmpty.unary_!) 
     { 
     <synthetic> val p3: String = o12.get._1; 
     val y: String = o12.get._2; 
     if ("Harold".==(p3)) 
      matchEnd9(scala.StringContext.apply("Last Name is ", "").s(y)) 
     else 
      case11() 
     } 
    else 
     case11() 
    }; 
    case11(){ 
    <synthetic> val o14: Option[(String, String)] = Person.unapply(x1); 
    if (o14.isEmpty.unary_!) 
     { 
     <synthetic> val p5: String = o14.get._1; 
     val y: String = o14.get._2; 
     if ("Magic".==(p5)) 
      matchEnd9(scala.StringContext.apply("Last Name is ", "").s(y)) 
     else 
      case13() 
     } 
    else 
     case13() 
    }; 
    case13(){ 
    matchEnd9("Unknown") 
    }; 

正如你所看到的,對於每一種情況下首先它匹配的對象調用unapply,那麼如果Option不爲空(所以它已經匹配),它檢查元組中的一個元素是否等於期望值,如果是,那麼它匹配這種情況下的閉包。