2012-03-10 184 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)我能想到的另一種方法是將整個匹配值賦給變量,是否有任何方法將一個case類構造函數模式匹配的值綁定到一個變量?

(我知道我可以在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這裏只是返回SheepNoneHair切割後。

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

這不起作用,因爲在模式匹配中,var「hair」只是從Sheep對象中提取的,所以它不是Sheep的字段,而是case塊的上下文中的變量。你可以做這樣的:

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的第一個塊作爲一個更好的選擇。你在案件陳述中知道你正在處理「羊」,所以沒有必要讓所有的「動物」必須處理可變的頭髮。一般來說,最小化可變性是一件好事,而另一種方法可以讓貓和狗也擁有不變的頭髮。 – 2012-03-12 09:44:44

+0

我完全同意你的觀點。但他的貓和狗班已經有可變的頭髮領域;-) – drexin 2012-03-12 14:56:25