2012-03-10 21 views
8

ho il seguente codice:Scala - designazione di un elemento abbinati a pattern matching

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 
    } 
    } 
} 

Le domande sono:

1) Quando il pattern matching ha successo con una pecora, come posso accedervi è capelli e cambiarlo? Si è lamentato della riassegnazione a val e ho quindi inserito var nel costruttore ma ...

2) Un altro modo in cui posso pensare è assegnare l'intero valore corrispondente a una variabile, esiste un modo per associare un valore corrispondente a un modello di costruttore case class in una variabile?

(So che potrei probabilmente eseguire lo schema su qualcosa come s: Sheep e quindi chiamare s.changeHairTo(None) ma quello è il modo meno preferibile).

risposta

25

È possibile utilizzare @ per legare l'intero modello alla variabile nella versione

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 
    } 
    } 
} 

Ma non è necessario utilizzare var. Ecco una versione più funzionale del tuo snippet. what qui restituisce Sheep con NoneHair dopo il taglio.

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

questo non funziona, perché nel modello che corrisponde alla var "hair" viene estratto dall'oggetto Sheep in modo che non sia il campo di Sheep, ma una variabile nel contesto del blocco del caso. Si potrebbe fare così:

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 
    } 
    } 
} 

Basta dire degli animali ha un campo capelli mutabile ed è possibile impostare senza il cast per il tipo giusto.

+0

Mentre funziona, preferirei il primo blocco di 4e6 come alternativa migliore. Nella dichiarazione del caso sai che hai a che fare con un 'Sheep', quindi non è necessario che tutti gli animali abbiano a che fare con capelli mutabili. In generale, ridurre al minimo la mutabilità è una buona cosa, e l'approccio alternativo consente a cani e gatti di avere capelli immutabili. –

+0

Sono assolutamente d'accordo con te in entrambi i punti. Ma le sue classi Cat e Dog hanno già dei campi mutabili ;-) – drexin