2012-03-10 24 views
8

Tôi có đoạn mã sau:Scala - chỉ định một mục phù hợp trong mô hình kết hợp

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

Các câu hỏi là:

1) Khi khớp mẫu thành công với một con chiên, làm thế nào tôi có thể truy cập nó là tóc và thay đổi nó? Nó phàn nàn về việc chuyển nhượng lại val, và sau đó tôi đã đặt var trong hàm dựng nhưng vẫn ...

2) Một cách nữa tôi có thể nghĩ là gán toàn bộ giá trị khớp với biến, có cách nào để ràng buộc một giá trị phù hợp với một số mô hình constructor lớp trường hợp cho một biến?

(Tôi biết rằng tôi có thể có thể khớp mẫu trên một cái gì đó như s: Sheep và sau đó gọi s.changeHairTo(None) nhưng đó là cách ít thích hợp nhất).

Trả lời

25

Bạn có thể sử dụng @ để ràng buộc toàn bộ mô hình để biến trong phiên bản của bạ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 
    } 
    } 
} 

Nhưng bạn không cần phải sử dụng var. Đây là phiên bản chức năng hơn của đoạn mã của bạn. what tại đây chỉ trả về Sheep với NoneHair sau khi cắt.

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

điều này không hoạt động, bởi vì trong mẫu phù hợp với var "tóc" chỉ được trích xuất từ ​​đối tượng cừu để nó không phải là trường của cừu, nhưng một biến trong bối cảnh của khối trường hợp. Bạn có thể làm điều đó như sau:

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

Chỉ cần nói rằng động vật có lông trường có thể thay đổi và bạn có thể đặt nó mà không đúc nó đúng loại.

+0

Trong khi công trình này, tôi muốn khối đầu tiên của 4e6 là lựa chọn tốt hơn. Bạn biết trong trường hợp tuyên bố rằng bạn đang đối phó với một 'Sheep', vì vậy không có yêu cầu để làm cho tất cả 'Animal' phải đối phó với mái tóc có thể thay đổi. Nói chung, giảm thiểu khả năng biến đổi là một điều tốt, và cách tiếp cận thay thế cho phép mèo và chó có mái tóc bất biến. –

+0

Tôi hoàn toàn đồng ý với bạn ở cả hai điểm. Nhưng các lớp Cat và Dog của anh ta đã có các trường tóc có thể thay đổi được ;-) – drexin

Các vấn đề liên quan