Scala模式匹配的`@`操作符 2016-11-21 11:52:43 阅读Spark源码的时候,经常碰到模式匹配中带着@这样的写法,如: ``` object CombineLimits extends Rule[LogicalPlan] { def apply(plan: LogicalPlan): LogicalPlan = plan transform { case ll @ Limit(le, nl @ Limit(ne, grandChild)) => Limit(If(LessThan(ne, le), ne, le), grandChild) } } ``` 大部分介绍Scala模式匹配的资料中都没有提到@的作用,今天特意研究了下他的用法:当需要处理匹配的对象本身时就可以用@将匹配对象绑定到一个变量上。 举例说明,我们定义个Person类: ``` scala> case class Person(name: String, age: Int) defined class Person ``` 然后实例化: ``` scala> val b = Person("Stan", 100) b: Person = Person(Stan,100) ``` 分别体会下以下几种用法: 首先是@的用法,p表示匹配的对象本身,当我们需要使用匹配中的对象时,就需要用@了。 ``` scala> b match { | case p @ Person(_, age) => println(s"${p.name}, age: $age") | case _ => println("Not a person") | } Stan, age: 100 ``` 还有一种用法,和上面的@用法很相似,不过是常见的类型匹配,这里的p也是一个匹配上的对象,和上面的区别是,这里p需要定义类型,而上面@的用法是个对象,对象中的age变量,我们是可以直接用的。 ``` scala> b match { | case p: Person => println(p.name) | case _ => println("Not a person") | } Stan ``` 在看下这种用法,这种是不带`@`或`:`的,匹配成功后,我们可以使用age变量,但是无法引用匹配的对象本身。 ``` scala> b match { | case Person(_, age) => println(s"age: $age") | case _ => println("Not a person") | } age: 100 ``` 这么对比来看就很容理解模式匹配中`@`的用法了。 ### 附:关于不同类型的匹配 以下这种case执行会出错: ``` val a = 5 a match { case p: Person => println(p.name) case _ => println("Not a person") } ``` 提示: ``` <console>:12: error: scrutinee is incompatible with pattern type; found : Person required: Int case p: Person => println(p.name) ``` 这是应为编译器已经推断出a的类型为Int,已经确定无法匹配Person,就出错了。 如果要实现类型的效果怎么办?可以这么实现: ``` scala> def testMatch(ar: Any) { | ar match { | case Person(_, age) => println(s"age: $age") | case _ => println("Not a person") | } | } testMatch: (ar: Any)Unit scala> testMatch(a) Not a person ``` 参考资料: - <http://stackoverflow.com/questions/20748858/pattern-matching-symbol> - <http://stackoverflow.com/questions/2359014/scala-operator> - <http://stackoverflow.com/questions/2651994/scala-wont-pattern-match-with-java-lang-string-and-case-class> 非特殊说明,均为原创,原创文章,未经允许谢绝转载。 原始链接:Scala模式匹配的`@`操作符 赏 Prev 解决使用Hive创建表出现JDODataStoreException: An exception was thrown while adding/validati的问题 Next 解决Mac下使用pip安装M2Crypto报错的问题