bigbull_提的问题,说在看akka的源码时,模式匹配有这样的用法,之前没有看到过:
def isManagementMessage(msg: Any): Boolean =
msg match {
case _: AutoReceivedMessage | _: Terminated | _: RouterManagementMesssage ⇒ true
case _ ⇒ false
}
自己尝试:
val a = 1
val b = a match { case _:String | _:Int => "str or int" }
却报错。
这是模式匹配可以对多个条件一起匹配的情况。假设有2个case class
定义如下:
scala> case class A(p1:Int, p2:Int)
defined class A
scala> case class B(p1:String, p2:String)
defined class B
现在我们想在模式匹配的时候,判断目标是否匹配A或B,可以这样写:
scala> def foo(msg:Any) = msg match { case A(_,2) | B(_,_) => println("ok") }
foo: (msg: Any)Unit
scala> foo(A(1,2))
ok
上面使用的是构造器模式混合通配符,如果我们不关心匹配时解构参数,只关心类型,可以用下面的方式来写:
scala> def foo(msg:Any) = msg match { case _:A | _:B => println("ok") }
foo: (msg: Any)Unit
scala> foo(A(1,2))
ok
这里注意,上面的类型匹配不能简化为 case _: A | B
因为这样写B代表的是伴生对象,是常量匹配:
scala> def foo(msg:Any) = msg match { case _:A | B => println("ok") }
foo: (msg: Any)Unit
scala> foo(A(1,2))
ok
scala> foo(B(1,2))
<console>:13: error: type mismatch;
found : Int(1)
required: String
foo(B(1,2))
^
scala> foo(B)
ok
上面的匹配表达式表示匹配A类型,或者B伴生对象(常量)。
而原先测试时,使用的
scala> val a = 1 // 这里已经推导a为Int类型
scala> val b = a match { case _:String | _:Int => "str or int" }
<console>:8: error: scrutinee is incompatible with pattern type;
这其实也可以给出警告而不是错误,scala编译器比较严格直接报错误了,要通过编译,可以把a的类型设置的泛一些:
scala> val a:Any = 1
a: Any = 1
scala> val b = a match { case _:String | _:Int => "str or int" }
b: String = str or int