2012-03-10 5 views
8

をマッチング:スカラ - のパターンでマッチしたアイテムの指定、私は次のコードを持っている

class Animal(hair: Option[Hair]) 

class Cat(var hair: Option[Hair]) extends Animal(hair) 
class Dog(var hair: Option[Hair]) extends Animal(hair) 
class Sheep(var hair: Option[Hair]) extends Animal(hair) 

//then somewhere else: 

def what(animal: Animal) { 

    animal match { 
    case Cat(hair) => println("processing cat, hair=" + hair) 
    case Dog(hair) => println("processing dog, hair=" + hair) 
    case Sheep(hair) => { 
     println("processing sheep, cutting hair...") 
     hair = None 
    } 
    } 
} 

質問は以下のとおりです。

1)パターンマッチングは、私はそれが髪のアクセスすることができますどのように羊と成功した場合それを変更しますか?それはvalへの再割り当てに不平を言った、そして私はvarをコンストラクタに置いたが、まだ...

2)私が考えてもいいもう一つの方法は、一致した値全体を変数に代入することです。いくつかの大文字と小文字のクラスコンストラクタパターンによってマッチした値を変数にバインドしますか?

(私はおそらくs: Sheepのようなものにパターンマッチしてから、s.changeHairTo(None)と呼ぶことができますが、それは最も好ましからざる方法です)。

答えて

25

あなたは

class Animal(hair: Option[Hair]) 
case class Cat(var hair: Option[Hair]) extends Animal(hair) 
case class Dog(var hair: Option[Hair]) extends Animal(hair) 
case class Sheep(var hair: Option[Hair]) extends Animal(hair) 

def what(animal: Animal) { 
    animal match { 
    case Cat(hair) => println("processing cat, hair=" + hair) 
    case Dog(hair) => println("processing dog, hair=" + hair) 
    case s @ Sheep(hair) => { 
     println("processing sheep, cutting hair...") 
     //cut(hair) 
     s.hair = None 
    } 
    } 
} 

お使いのバージョンでは、変数にパターン全体をバインドする@を使用することができますしかし、あなたはvarを使用する必要はありません。あなたのスニペットのより機能的なバージョンです。 whatここにちょうどがあります。NoneHairを返してください。

trait Animal 
case class Cat(hair: Option[Hair]) extends Animal 
case class Dog(hair: Option[Hair]) extends Animal 
case class Sheep(hair: Option[Hair]) extends Animal 

def what(animal: Animal): Animal = 
    animal match { 
    case Cat(hair) => 
     println("processing cat, hair=" + hair) 
     animal 
    case Dog(hair) => 
     println("processing dog, hair=" + hair) 
     animal 
    case Sheep(hair) => { 
     println("processing sheep, cutting hair...") 
     //cut(hair) 
     Sheep(None) 
    } 
    } 
4

パターンマッチングでは、「髪」は「羊」オブジェクトから単に抽出されるため、羊のフィールドではなく、ケースブロックのコンテキスト内の変数です。

class Hair 

trait Animal { 
    var hair: Option[Hair] 
} 
case class Cat(var hair: Option[Hair]) extends Animal 
case class Dog(var hair: Option[Hair]) extends Animal 
case class Sheep(var hair: Option[Hair]) extends Animal 

//then somewhere else: 

def what(animal: Animal) { 

    animal match { 
    case Cat(hair) => println("processing cat, hair=" + hair) 
    case Dog(hair) => println("processing dog, hair=" + hair) 
    case Sheep(hair) => { 
     println("processing sheep, cutting hair...") 
     animal.hair = None 
    } 
    } 
} 

ちょうどそれが変更可能なフィールドの毛を持っており、あなたが正しい型にキャストせずにそれを設定することができます動物を教えて:あなたはこのようにそれを行うことができます。

+0

これは機能しますが、私は4e6の最初のブロックを使用する方がよいでしょう。ケースステートメントの中で、「羊」を扱っていることを知っているので、すべての「動物」が変更可能な髪を扱わなければならないという要件はありません。一般的に言えば、変更を最小限に抑えることは良いことです。代替アプローチでは、猫や犬にも変わらない髪ができます。 –

+0

私は両方の点であなたに完全に同意します。しかし、彼の猫と犬のクラスはすでに変更可能な髪のフィールドを持っています;-) – drexin