Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala中的模式匹配或isInstanceOf_Scala_Reflection - Fatal编程技术网

Scala中的模式匹配或isInstanceOf

Scala中的模式匹配或isInstanceOf,scala,reflection,Scala,Reflection,假设我有以下类层次结构: trait A; class A1 extends A; class A2 extends A 现在我需要过滤List[A]中的A1实例。我使用模式匹配或isInstanceOf as.filter(cond(_){case _: A1 => true}) // use pattern matching as.filter(_.isInstanceOf[A1]) // use isInstanceOf 它的工作原理相同吗?您喜欢什么?为什么不使用colle

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

trait A; class A1 extends A; class A2 extends A
现在我需要过滤
List[A]
中的
A1
实例。我使用模式匹配或
isInstanceOf

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

它的工作原理相同吗?您喜欢什么?

为什么不使用collect?这样做的另一个好处是,返回的列表将是正确的类型(列表[A1]而不是列表[A])

它的工作原理相同吗

将生成相同的答案,但在每种情况下都会发出不同的代码,正如您所期望的那样

您可以检查在每种情况下生成的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
要检查IL的
as.filter(cond({case}:A1=>true})
版本,请执行以下操作

javap -c 'Filterer$$anonfun$filter1$1'
javap -c 'Filterer$$anonfun$filter1$1$$anonfun$apply$1'
然后要检查IL的
as.filter(u.isInstanceOf[A1])
版本,您可以执行以下操作

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

cond
”版本使用了更多的中间值,并实例化了更多表示所涉及的额外匿名函数的对象。

虽然接受的答案给了您一个很好的建议,但请注意,scala中的typecase与将
isInstanceOf
asInstanceOf
结合使用并无不同。这两个例子大致相当:

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]}

丑陋的东西应该看起来丑陋。

这也适用于匹配Java类型,而不仅仅是Scala类型(从2.11.4开始测试)
val a1s = as.collect{case x if x.isInstanceOf[A1] => x.asInstanceOf[A1]}