17
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语句有缺点吗?什么时候应该使用哪种方法(以及这里应该使用哪种方法以及为什么)?

4

4 回答 4

20

你可以这样过滤:

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

IMO,这更具可读性。

于 2012-06-27T15:13:29.297 回答
14

使用没有问题isInstanceOf,只要你不使用asInstanceOf

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

于 2012-06-27T15:37:55.843 回答
12

没有区别

猫 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();
      ()
    }
  }
}
于 2012-06-27T15:13:43.790 回答
11

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

在以下代码段中,使用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))
于 2012-06-27T15:34:18.133 回答