【发布时间】:2014-07-20 17:17:42
【问题描述】:
如果传递给方法的对象是可接受的类型,我需要执行相同的操作。下面例子中的第二种情况是否可以消除?
obj match {
case obj: String => print(obj)
case obj: Int => print(obj)
}
【问题讨论】:
标签: scala types pattern-matching
如果传递给方法的对象是可接受的类型,我需要执行相同的操作。下面例子中的第二种情况是否可以消除?
obj match {
case obj: String => print(obj)
case obj: Int => print(obj)
}
【问题讨论】:
标签: scala types pattern-matching
是的,这是可能的,但并非在所有情况下都可以。您可以在具体示例中使用 Scalas | 运算符:
scala> ("hello": Any) match { case s @ (_: String | _: Int) => println(s)}
hello
scala> ("1": Any) match { case s @ (_: String | _: Int) => println(s)}
1
但这个特定示例仅适用,因为 println 需要一个类型为 Any 的参数,这实际上就是您在此处所拥有的。
考虑这个例子:
scala> object X {def f(i: Int) = i.toString; def f(s: String) = s}
defined object X
scala> ("": Any) match { case s @ (_: String | _: Int) => X.f(s)}
<console>:9: error: overloaded method value f with alternatives:
(s: String)String <and>
(i: Int)String
cannot be applied to (Any)
("": Any) match { case s @ (_: String | _: Int) => X.f(s)}
^
问题在于,虽然有两种方法可以处理这两种类型,但编译器无法决定应该调用哪一种。这是因为编译器会为s 推断类型Any,因为它既可以是String 也可以是Int,并且编译器需要选择它们共同的超类型来履行这个契约。而且因为不存在采用Any 的方法f,所以会出现编译错误。在这种情况下,您需要分隔模式:
scala> ("hello": Any) match { case s: String => X.f(s) case i: Int => X.f(i)}
res6: String = hello
总而言之,您应该只在它们具有相同类型的情况下组合多个案例,否则您必须使用Any。不过,我建议不要使用Any,因为当代码更改时很容易引入打字错误。
【讨论】: