【问题标题】:When to use isInstanceOf and when to use a match-case-statement (in Scala)?何时使用 isInstanceOf 以及何时使用 match-case-statement(在 Scala 中)?
【发布时间】:2012-06-29 01:34:19
【问题描述】:
sealed class A
class B1 extends A    
class B2 extends A

假设我们有一个 A 类的对象列表: val l: List[A] = List(new B1, new B2, new B1, new B1)

我们要过滤掉 B1 类型的元素。 然后我们需要一个谓词,可以使用以下两种替代方法:

l.filter(_.isInstanceOf[B1])

或者

l.filter(_ match {case b: B1 => true; case _ => false})

就个人而言,我更喜欢第一种方法,但我经常阅读,应该更频繁地使用match-case 语句(原因我不知道)。

因此,问题是:使用isInstanceOf 代替match-case 语句是否有缺点?什么时候应该使用哪种方法(这里应该使用哪种方法以及为什么)?

【问题讨论】:

    标签: scala match


    【解决方案1】:

    match-case 的优点是您不必强制转换对象,以防您想对其执行依赖于其较窄类型的操作。

    在下面的sn-p中,使用isInstanceOf似乎没问题,因为你不执行这样的操作:

    if (obj.isInstanceOf[A]) println(obj)
    

    但是,如果您执行以下操作:

    if (obj.isInstanceOf[A]) {
      val a = obj.asInstanceOf[A]
      println(a.someField) // someField is declared by A
    }
    

    那么我会赞成使用match-case

    obj match {
      case a: A => println(a.someField)
      case _ =>
    }
    

    您必须包含“否则”情况有点烦人,但使用collect(由 om-nom-nom 暗示)可能会有所帮助,至少如果您使用从 Seq 继承的集合:

    collectionOfObj.collect{ case a: A => a}.foreach(println(_.someField))
    

    【讨论】:

      【解决方案2】:

      使用isInstanceOf没有问题,只要不使用asInstanceOf即可。

      同时使用两者的代码很脆弱,因为检查和强制转换是单独的操作,而使用匹配则需要一个操作来完成这两个操作。

      【讨论】:

        【解决方案3】:

        没有区别

        猫 t.scala:

        class A {
          def x(o: AnyRef) = o.isInstanceOf[A]
          def y(o: AnyRef) = o match {
            case s: A => true
            case _ => false
          }
        }
        

        $ scalac -print t.scala

        [[syntax trees at end of cleanup]]// Scala source: t.scala
        package <empty> {
          class A extends java.lang.Object with ScalaObject {
            def x(o: java.lang.Object): Boolean = o.$isInstanceOf[A]();
            def y(o: java.lang.Object): Boolean = {
              <synthetic> val temp1: java.lang.Object = o;
              temp1.$isInstanceOf[A]()
            };
            def this(): A = {
              A.super.this();
              ()
            }
          }
        }
        

        【讨论】:

          【解决方案4】:

          你可以这样过滤:

          l.collect{ case x: B1 => x }
          

          这更具可读性,IMO。

          【讨论】:

          • 并在最后为您提供更窄的类型 (List[B1])。
          • 看起来更具可读性,谢谢。但是这个语句中的默认情况是什么?在哪里可以阅读有关此快捷案例语句及其使用方式的更多背景信息?
          • @JohnThreepwood 看看this post。它不是最好的,但仍然非常好“收集的原因”。简而言之,collect 就像 map,但只对那些为您传递给此方法的 (partial) 函数定义的值起作用。在这种情况下,Scala 的模式匹配是在PartialFunction 之上完成的。此外,您需要使用大括号。
          • @om-nom-nom 感谢您提供更多信息和链接,这对您有很大帮助!
          猜你喜欢
          • 2014-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-15
          • 2014-01-16
          • 2015-09-06
          • 2021-05-31
          • 2016-02-11
          相关资源
          最近更新 更多