sealed class A
class B1 extends A
class B2 extends A
Run Code Online (Sandbox Code Playgroud)
假设我们有一个类对象列表A
:val l:List [A] = List(新B1,新B2,新B1,新B1)
我们想要过滤掉B1类型的元素.然后我们需要一个谓词,可以使用以下两种选择:
l.filter(_.isInstanceOf[B1])
Run Code Online (Sandbox Code Playgroud)
要么
l.filter(_ match {case b: B1 => true; case _ => false})
Run Code Online (Sandbox Code Playgroud)
就个人而言,我更喜欢第一种方法,但我经常阅读,应该match-case
更频繁地使用该语句(由于我不知道的原因).
因此,问题是:使用isInstanceOf
而不是使用match-case
声明有缺点吗?什么时候应该使用哪种方法(这里应该使用哪种方法以及为什么)?
om-*_*nom 17
你可以这样过滤:
l.collect{ case x: B1 => x }
Run Code Online (Sandbox Code Playgroud)
IMO,这更具可读性.
Mal*_*off 11
优点match-case
是您不必转换对象,以防您想要对其执行依赖于其较窄类型的操作.
在下面的代码片段中,使用isInstanceOf
似乎很好,因为您不执行此类操作:
if (obj.isInstanceOf[A]) println(obj)
Run Code Online (Sandbox Code Playgroud)
但是,如果您执行以下操作:
if (obj.isInstanceOf[A]) {
val a = obj.asInstanceOf[A]
println(a.someField) // someField is declared by A
}
Run Code Online (Sandbox Code Playgroud)
然后我会赞成使用match-case
:
obj match {
case a: A => println(a.someField)
case _ =>
}
Run Code Online (Sandbox Code Playgroud)
稍微烦人的是你必须包含"否则" - 例句,但使用collect
(如om-nom-nom所示)可能有所帮助,至少如果你使用从Seq继承的集合:
collectionOfObj.collect{ case a: A => a}.foreach(println(_.someField))
Run Code Online (Sandbox Code Playgroud)
没有区别
cat t.scala:
class A {
def x(o: AnyRef) = o.isInstanceOf[A]
def y(o: AnyRef) = o match {
case s: A => true
case _ => false
}
}
Run Code Online (Sandbox Code Playgroud)
$ 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();
()
}
}
}
Run Code Online (Sandbox Code Playgroud)