Scala中的模式匹配或isInstanceOf

时间:2014-08-27 15:09:50

标签: scala reflection

假设我有以下类层次结构:

trait A; class A1 extends A; class A2 extends A

现在我需要在A1中过滤List[A]个实例。我使用模式匹配或isInstanceOf

 as.filter(cond(_){case _: A1 => true}) // use pattern matching
 as.filter(_.isInstanceOf[A1]) // use isInstanceOf

它是否有效?你更喜欢什么?

3 个答案:

答案 0 :(得分:11)

你为什么不使用收藏?这具有额外的好处,即返回的列表将是正确的类型(List [A1]而不是List [A])

val a1s = as.collect { case x:A1 => x }

答案 1 :(得分:6)

虽然接受的答案会给你一个很好的建议,但请注意scala中的typecase与使用isInstanceOfasInstanceOf结合使用时没有区别。这两个例子大致相同:

def foo(x: Any) = x match {
   case s: String = println(s"$s is a String)
   case _ => println("something else")
}

def foo(x: Any) = x match {
   case _ if x.isInstanceOf[String] => println(s${x.asInstanceOf[String]} is a String)
   case _ => println("something else")
}

因此,在您的具体示例中,您使用的两个中的哪一个并不重要:您总是会做某种向下转换,这通常是可以避免的。

看看第二个版本是如何更加丑陋,因此更合适,因为你在函数式语言中做了一件“丑陋”的事情。

所以,我会选择

val a1s = as.collect{case x if x.isInstanceOf[A1] => x.asInstanceOf[A1]}

丑陋的事情应该看起来很难看。

答案 2 :(得分:1)

  

它是否有效?

将生成相同的答案,但每种情况下都会发出不同的代码,如您所料。

您可以检查在每种情况下生成的IL,如下所示。创建" test.scala"文件包含以下内容:

import PartialFunction.cond

trait A; class A1 extends A; class A2 extends A

class Filterer {
  def filter1(as: List[A]) =
    as.filter(cond(_){case _: A1 => true}) // use pattern matching

  def filter2(as: List[A]) =
    as.filter(_.isInstanceOf[A1]) // use isInstanceOf
}

然后运行:

scalac test.scala

要检查as.filter(cond(_){case _: A1 => true})版本的IL,请执行

javap -c 'Filterer$$anonfun$filter1$1'
javap -c 'Filterer$$anonfun$filter1$1$$anonfun$apply$1'

然后检查as.filter(_.isInstanceOf[A1])版本的IL,你可以

javap -c 'Filterer$$anonfun$filter2$1'

" cond" version使用更多中间值并实例化更多表示所涉及的额外匿名函数的对象。