Когда использовать isInstanceOf и когда использовать оператор match-case (в Scala)?
sealed class A
class B1 extends A
class B2 extends A
Предположим у нас есть список объектов класса A
:
val l: List[A] = список (новый B1, новый B2, новый B1, новый B1)
и мы хотим отфильтровать элементы типа B1. Тогда нам нужен предикат и можно использовать следующие две альтернативы:
l.filter(_.isInstanceOf[B1])
или
l.filter(_ match {case b: B1 => true; case _ => false})
лично мне больше нравится первый подход, но я часто читаю, нужно использовать match-case
заявление чаще (по причинам, которые я не делаю знать.)
поэтому вопрос: есть ли недостатки использования isInstanceOf
вместо match-case
заявление ? Когда следует использовать, какой подход (и какой подход следует использовать и почему) ?
4 ответов
преимущество 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))
нет проблем с использованием isInstanceOf
, пока вы не используете asInstanceOf
.
код, который использует оба, хрупок, потому что проверка и литье-это отдельные действия, тогда как при использовании сопоставления у вас есть одно действие, выполняющее оба.
нет никакой разницы
cat t.скала:
class A {
def x(o: AnyRef) = o.isInstanceOf[A]
def y(o: AnyRef) = o match {
case s: A => true
case _ => false
}
}
$ scalac-печать t.скала!--3-->
[[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();
()
}
}
}