2012-06-27 18 views
11
sealed class A 
class B1 extends A  
class B2 extends A 

私たちはクラスAのオブジェクトのリストを持っていると仮定すると:リスト[A] =リスト(新B1、新しいB2、新しいB1、新しいB1)isInstanceOfを使用するタイミングと、(Scalaで)match-case-statementを使用するタイミングを教えてください。

そして、我々はフィルタリングしたい:ヴァルリットル タイプB1の要素。 はその後、我々は、述語を必要とし、次の二つの選択肢使用することができます

l.filter(_.isInstanceOf[B1]) 

それとも

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

個人的に、私はより多くの最初のアプローチを好むが、私は頻繁に読んで、人はより多くのmatch-caseステートメントを使用する必要がありますしばしば(私が知らない理由で)。

したがって、質問はmatch-caseの代わりにisInstanceOfを使用するという欠点がありますか?どのアプローチをいつ使うべきですか(そして、どのアプローチをここで使用すべきか、そしてその理由は何か)?

答えて

17

あなたはそのようにフィルタリングすることができます:

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

IMO、はるかに読み取り可能であること。

+3

そして最後に狭い型を与えます( 'List [B1]')。 –

+0

もっと読みやすく見える、ありがとう。しかし、この声明のデフォルトのケースは何でしょうか?このショートカットケースのステートメントに関する詳細な背景情報とその使用方法はどこで確認できますか? –

+0

@JohnThreepwood [この投稿](http://ochafik.com/blog/?p=393)を見てください。それは最高のものではありませんが、「収集する理由」はまだかなり良いです。簡単に言うと、collectはmapのようですが、このメソッドに渡す*(部分)*関数のために定義された値に対してのみ作業を行います。この場合のScalaのパターンマッチングは[PartialFunction](http://stackoverflow.com/questions/5668053/scala-partial-functions)の上で実行されます。また、中括弧を使用する必要があります。 –

7

には違いありません

猫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(); 
    () 
    } 
    } 
} 
+0

スケーラコンパイラが何をするのか、背景情報に感謝します。 –

9

match-caseの利点は、あなたがいないということですより狭い型に依存する操作を実行したい場合に備えてオブジェクトをキャストする必要があります。あなたが行う場合は、次の、しかし

if (obj.isInstanceOf[A]) println(obj) 

:その後、私は「

if (obj.isInstanceOf[A]) { 
    val a = obj.asInstanceOf[A] 
    println(a.someField) // someField is declared by A 
} 

あなたは、このような操作を実行していないので、isInstanceOfを使用して、次のスニペットで

は、罰金のようですdを使用するほうが好ましい match-case

obj match { 
    case a: A => println(a.someField) 
    case _ => 
} 

これは少し面倒ですあなたは「それ以外」-caseが、collect(OM-NOM-NOMでほのめかしとして)を使用すると、あなたがコレクションでは動作し、少なくとも場合は、助けることができる配列を継承を含める必要があることINGの:

collectionOfObj.collect{ case a: A => a}.foreach(println(_.someField)) 
+0

あなたの良い例をありがとう、非常に良い。 –

9

何もありませんあなたがasInstanceOfを使用しない限り、isInstanceOfを使用している問題。

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

+0

ヒントありがとう、私はそれを注意します。 –

関連する問題