2012-03-10 12 views
8

tengo el siguiente código:Scala - la designación de un elemento coincidente en la coincidencia de patrones

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

Las preguntas son:

1) Cuando la coincidencia de patrones tiene éxito con una oveja, ¿cómo puedo acceder es el pelo y cambiarlo? Se quejó de la reasignación a val, y luego coloqué var en el constructor pero aún ...

2) Otra forma en que puedo pensar es asignar el valor coincidente completo a una variable, ¿hay alguna forma de vincular un valor que coincida con un patrón de constructor de clase de caso a una variable?

(Sé que probablemente podría coincidir con el patrón en algo como s: Sheep y luego llamar al s.changeHairTo(None), pero esa es la forma menos preferible).

Respuesta

25

Puede utilizar @ de obligar a todo el patrón variable en su versión

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

Pero usted no tiene que utilizar var. Aquí hay una versión más funcional de su fragmento. what aquí simplemente devuelve Sheep con NoneHair después del corte.

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

esto no funciona, porque en el patrón coincidente, la var "pelo" se extrae del objeto Ovejas para que no sea el campo de Ovejas, sino una variable en el contexto del bloque de casos. Se podía hacerlo de esta manera:

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

Sólo decirle animal que tiene un pelo de campo mutable y se puede establecer sin poner al tipo correcto.

+0

Mientras esto funciona, preferiría el primer bloque de 4e6 como una mejor alternativa. En el enunciado del caso, usted sabe que está tratando con una 'Oveja', por lo que no es necesario hacer que todos los 'Animales' tengan que tratar con el cabello mutable. En términos generales, minimizar la mutabilidad es algo bueno, y el enfoque alternativo permite que los perros y los gatos también tengan un cabello inmutable. –

+0

Estoy totalmente de acuerdo con usted en ambos puntos. Pero sus clases de gato y perro ya tienen campos de pelo mutables ;-) – drexin

Cuestiones relacionadas