【问题标题】:How to check that Scala object is either instance of either A or B?如何检查 Scala 对象是 A 还是 B 的实例?
【发布时间】:2014-07-20 17:17:42
【问题描述】:

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

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

【问题讨论】:

    标签: scala types pattern-matching


    【解决方案1】:

    是的,这是可能的,但并非在所有情况下都可以。您可以在具体示例中使用 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,因为当代码更改时很容易引入打字错误。

    【讨论】:

    • 实际上,我在问题中提供的示例与我的想法有点不同。我有一个带有子类 B、C、D、E 和 F 的抽象类 A 和一个接受 A 的方法。我需要检查传递的对象的类型并为 B、C 和 D 调用相同的方法,但调用专用方法对于 E 和 F。我正在考虑为 B、C 和 D 添加一个公共超类,但我认为可能还有另一种方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 2010-09-14
    • 2015-08-03
    相关资源
    最近更新 更多