2016-12-26 74 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不为空(所以它已经匹配),它检查元组中的一个元素是否等于期望值,如果是,那么它匹配这种情况下的闭包。