2012-03-10 181 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