2016-08-09 6 views
1

"これはどのように動作するのですか"より良い説明がありますか?私はそれが正常に動作しますクラスのそれぞれの前caseを追加する場合はもちろんなぜノンケースクラスに対してパターンマッチングを適用できないのですか?

Cannot resolve symbol 'Val' Cannot resolve symbol 'Sup'

class TestShortMatch[T <: AnyRef] { 
    def foo(t: T): Unit = { 
    val f = (_: Any) match { 
     case Val(t) => println(t) 
     case Sup(l) => println(l) 
    } 
    } 

    class Val(t: T) 
    class Sup(l: Number) 
} 

とコンパイラの苦情:私は、私はこの1つを試してみました意味します。しかし、その理由は何ですか?コンパイラはいくつかの最適化を行い、特定のバイトコードを生成しますか?

+0

標準的なリファレンスは、Scalaのプログラミングの第24章です。この本は第3版にあるので、第1版はオンラインですhttp://www.artima.com/pins1ed/extractors.html –

答えて

5

理由は2倍です。パターンマッチングはちょうどextractorscase classesを使用するための構文的な砂糖です。あなたには無料のカップルメソッドがあります。その1つは主コンストラクタに対応する抽出メソッドです。


あなたが仕事に上記のあなたの例をしたい場合は、オブジェクトValSupunapplyメソッドを定義する必要があります。 (あなたがあなたのフィールドval秒を行う必要がありますので、のみvalフィールド上で定義されている)を使用すると、抽出方法を必要とするだろうことを行うには:

class Val[T](val t: T) 
class Sup(val l: Number) 

object Val { 
    def unapply[T](v: Val[T]): Option[T] = Some(v.t) 
} 
object Sup { 
    def unapply(s: Sup): Option[Number] = Some(s.l) 
} 

そして、それはあなたがval Val(v) = new Val("hi")ような何かを行うことができますポイント。しかししばしば、あなたのクラスをcaseクラスにする方が良いでしょう。次に、余分なエクストラクタを定義する唯一の時間です。

(私は参照を見つけることができないよう先の)通常の例では座標です:

case class Coordinate(x: Double, val: Double) 

そして、あなたがに変換する

object Polar { 
    def unapply(c: Coordinate): Option[(Double,Double)] = {...} 
} 
object Cartesian { 
    def unapply(c: Coordinate): Option[(Double,Double)] = Some((c.x,c.y)) 
} 

のようなカスタム抽出を定義することができます2つの異なる表現、パターンマッチのすべて。

3

任意のクラスに対してパターンマッチングを使用できますが、オブジェクトを "構成解除"するためにはan unapply methodを実装する必要があります。

ケースクラスでは、未適用メソッドはコンパイラによって自動的に生成されるため、自分で実装する必要はありません。

1

あなたがmatch exp { case Val(pattern) => ... case ... }を書くとき、それはこのようなものに相当します。それはマッチが成功したかどうかを確認するためにコンパニオンオブジェクトのunapplyメソッドの結果を使用して、ある

match Val.unapply(exp) { 
    case Some(pattern) => 
    ... 
    case _ => 
    // code to match the other cases goes here 
} 

ケースクラスを定義すると、適切なunapplyメソッドを持つコンパニオンオブジェクトが自動的に定義されます。通常のクラスではそうではありません。その動機は、ケースクラス(例えば、equalshashCodeなど)のために自動的に定義される他のものと同じです。クラスをケースクラスとして宣言することによって、クラスの行動する。それを考えると、自動生成されたものがあなたの望むことをする可能性は十分あります。一般的なクラスでは、これらのメソッドを動作させたいように定義するのはあなた次第です。

ケースクラスのパラメータはデフォルトでvalであることに注意してください。これは通常のクラスでは当てはまりません。したがって、クラスclass Val(t: T)には外部からtにアクセスする方法がありません。したがって、tという値になるunapplyメソッドを定義することさえできません。これは、通常のクラスに対して自動的に生成されるunapplyを取得しない別の理由です。すべてのパラメータがvalでない限り、生成することはできません。

関連する問題