如何检查Scala对象是A还是B的实例?

时间:2014-05-30 20:46:05

标签: scala types pattern-matching

如果传递给方法的对象是可接受的类型,我需要执行相同的操作。是否可以消除下面例子中的第二种情况?

obj match {
  case obj: String => print(obj)
  case obj: Int => print(obj)
}

1 个答案:

答案 0 :(得分:4)

是的,这是可能的,但不是在所有情况下都是如此。您可以在特定示例中使用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)}
                                                                   ^

问题是虽然有两种方法可以处理这两种类型,但编译器无法决定应该调用哪种类型。这是因为编译器将推断Any的类型s,因为它可以是StringInt,并且编译器需要选择它们的公共超类型来完成此契约。并且因为不存在采用f的方法Any,所以会出现编译错误。在这种情况下,您需要分离模式:

scala> ("hello": Any) match { case s: String => X.f(s) case i: Int => X.f(i)}
res6: String = hello

总之,如果他们不必与Any生活在一起,那么他们应该只将多个案例组合在一起。虽然,我建议不要使用Any,但在代码更改时引入输入错误太容易了。