Ответ 1
Вы можете так фильтровать:
l.collect{ case x: B1 => x }
Это более читаемо, ИМО.
sealed class A
class B1 extends A
class B2 extends A
Предполагая, что у нас есть список объектов класса A
: val l: Список [A] = Список (новый B1, новый B2, новый B1, новый B1)
И мы хотим отфильтровать элементы типа B1. Тогда нам нужен предикат и он может использовать следующие две альтернативы:
l.filter(_.isInstanceOf[B1])
или
l.filter(_ match {case b: B1 => true; case _ => false})
Лично мне больше нравится первый подход, но я часто читаю, нужно использовать инструкцию match-case
чаще (по причинам, которые я не знаю).
Поэтому возникает вопрос: существуют ли недостатки использования isInstanceOf
вместо инструкции match-case
? Когда следует использовать какой подход (и какой подход следует использовать здесь и почему)?
Вы можете так фильтровать:
l.collect{ case x: B1 => x }
Это более читаемо, ИМО.
Преимущество 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 _ =>
}
Немного досадно, что вам нужно включить "в противном случае" -case, но использование collect
(как намечено ом-ном-ном) могло бы помочь, по крайней мере, если вы работаете с коллекциями, наследуемыми от Seq:
collectionOfObj.collect{ case a: A => a}.foreach(println(_.someField))
Нет проблем с использованием isInstanceOf
, если вы не используете asInstanceOf
.
Код, который использует оба метода, является хрупким, потому что проверка и литье являются отдельными действиями, тогда как при использовании соответствия у вас есть одно действие, выполняющее оба.
Нет разницы
cat 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();
()
}
}
}