2011-08-14 26 views
7

Tôi hiện đang tự hỏi về việc tạo một đối tượng/lớp/đặc điểm phù hợp với một đặc điểm cho nhiều tham số kiểu. Hãy nói rằng tôi cóThành phần có cùng đặc điểm, nhưng các tham số kiểu khác nhau

trait Dependent[T]{ 
    def observeCritereaChanged(oldValue:T, newValue:T):Unit 
} 

Tôi muốn để có thể xác định một số đặc điểm mà thực hiện phụ thuộc cho hai tham số kiểu khác nhau, ví dụ

trait IntStrDependent extends Dependent[Int] with Dependent[String] 

Vì vậy mà trường hợp của IntStrDependent đặc điểm của tôi sẽ phải xác định số observeCritereaChanged cho cả hai loại:

class MyDependent extends IntStrDependent { 
    def observeCritereaChanged(oldValue:Int, newValue:Int) = //... 
    def observeCritereaChanged(oldValue:String, newValue:String) = //... 
} 

Cho đến nay, các nỗ lực của tôi đã gặp phải lỗi biên dịch khi thử để tạo ra các đặc điểm IntStrDependent:

scala> trait IntStrDependent extends Dependent[Int] with Dependent[String] 
<console>:8: error: illegal inheritance; 
self-type IntStrDependent does not conform to Dependent[Int]'s selftype Dependent[Int] 
     trait IntStrDependent extends Dependent[Int] with Dependent[String] 
            ^
<console>:8: error: illegal inheritance; 
self-type IntStrDependent does not conform to Dependent[String]'s selftype Dependent[String] 
     trait IntStrDependent extends Dependent[Int] with Dependent[String] 
                 ^

Vì vậy, câu hỏi của tôi là: Có cách nào để làm những gì tôi đang cố gắng để làm gì (nếu như vậy, như thế nào) hoặc đây là một nguyên nhân bị mất vì Scala là không được xây dựng để làm điều này?

Trả lời

3

Câu hỏi hay. Tôi không nghĩ rằng bạn có thể làm những gì bạn muốn trực tiếp.

Một cách tiếp cận khác là trait IntStrDependent extends Dependent[Either[Int, String]] nhưng cách đó không giải quyết được vấn đề. Có lẽ một biến thể của encoding of union types của Miles Sabin cho phép một cái gì đó tuyệt vời được thực hiện.

Tôi nghĩ rằng lựa chọn tốt nhất là để giữ cho nó đơn giản,

trait Dependent[T]{ 
    def observeCritereaChanged(oldValue:T, newValue:T):Unit 
} 

trait IntStrDependent { 
    val I: Dependent[Int] 
    val S: Dependent[String] 
} 

object MyDependent extends IntStrDependent { 
    object I extends Dependent[Int] { 
    def observeCritereaChanged(oldValue:Int, newValue:Int) {} 
    } 
    object S extends Dependent[String] { 
    def observeCritereaChanged(oldValue:String, newValue:String) {} 
    } 
} 

Để sử dụng MyDependent, người ta phải chọn một cách rõ ràng Int hoặc String biến thể, như trong

MyDependent.I.observeCritereaChanged(1, 2) 

Theo tôi, làm cho loại phụ thuộc rõ ràng là một điều tốt anyway.

+0

Đó là những gì tôi thường làm. –

+0

Đọc thú vị mà bạn đã liên kết. Điều đó chắc chắn trả lời câu hỏi của tôi, nhưng tôi nghĩ rằng tôi sẽ đi với cách tiếp cận của bạn: Chuyển từ một 'là a' thành một mối quan hệ' có một 'sẽ ổn cho ứng dụng của tôi – Dylan

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