17
sealed class A
class B1 extends A    
class B2 extends A

クラスのオブジェクトのリストがあると仮定しますA: val l: List[A] = List(new B1, new B2, new B1, new B1)

そして、タイプ B1 の要素を除外したいと考えています。次に、述語が必要であり、次の 2 つの選択肢を使用できます。

l.filter(_.isInstanceOf[B1])

または

l.filter(_ match {case b: B1 => true; case _ => false})

個人的には、最初のアプローチの方が好きですが、よく読んだことがありますが、match-caseステートメントをもっと頻繁に使用する必要があります(理由はわかりません)。

したがって、質問は次のとおりです。ステートメントisInstanceOfの代わりに使用することの欠点はありますか? match-caseいつどのアプローチを使用する必要がありますか (ここでどのアプローチを使用する必要があるか、またその理由) ?

4

4 に答える 4

20

次のようにフィルタリングできます。

l.collect{ case x: B1 => x }

それははるかに読みやすいです、IMO。

于 2012-06-27T15:13:29.297 に答える
14

isInstanceOfを使用しない限り、使用しても問題ありませんasInstanceOf

両方を使用するコードは脆弱です。これは、チェックとキャストが別々のアクションであるのに対し、マッチングを使用すると、両方を行う単一のアクションになるためです。

于 2012-06-27T15:37:55.843 に答える
12

違いはありません

猫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();
      ()
    }
  }
}
于 2012-06-27T15:13:43.790 に答える
11

の利点は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))
于 2012-06-27T15:34:18.133 に答える