Когда использовать 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 ответов


вы можете фильтровать так:

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 _ =>
}

это немного раздражает, что вы должны включить "в противном случае"-случай, но использование 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();
      ()
    }
  }
}