2012-06-30 24 views
14
scala> class C 
defined class C 

scala> class subC extends C 
defined class subC 

scala> class A { type T = C} 
defined class A 

scala> class subA extends A { override type T = subC} 
<console>:10: error: overriding type T in class A, which equals C; 
type T has incompatible type 
     class subA extends A { override type T = subC} 
             ^

Trong ví dụ trên, tôi nhận được thông báo lỗi, tôi không thể ghi đè trường loại trong lớp A (ngay cả khi loại được chọn subC kéo dài lớp C).Có thể ghi đè trường loại không?

Có thể ghi đè trường kiểu có thể không? Và nếu có, có gì sai với ví dụ trên?

Trả lời

22

Bạn sẽ không nói về 'ghi đè' đối với các loại, nhưng thay vì thu hẹp giới hạn của chúng.

  1. type T ... không giới hạn
  2. type T <: C ... TC hoặc một subtype của C (được gọi là trên ràng buộc)
  3. type T >: C ... TC hoặc một supertype của C (được gọi là giới hạn dưới)
  4. type T = C ... T là chính xác C (loại bí danh)

Do đó, nếu T là thành viên loại đặc điểm A, và SubA là một subtype của A, trong trường hợp (2) SubA có thể thu hẹp T đến một subtype đặc biệt hơn C, trong khi đó (3) nó có thể thu hẹp nó thành một siêu kiểu cao hơn là C. Trường hợp (1) không áp đặt bất kỳ hạn chế nào đối với SubA, trong khi trường hợp (4) có nghĩa là T là 'cuối cùng' để nói.


này có hậu quả đối với các useability của T trong A -liệu nó có thể xuất hiện như kiểu một đối số phương pháp hay kiểu trả về của phương pháp.

Ví dụ:

trait C { def foo =() } 
trait SubC extends C { def bar =() } 

trait MayNarrow1 { 
    type T <: C // allows contravariant positions in MayNarrow1 
    def m(t: T): Unit = t.foo // ...like this 
} 

object Narrowed1 extends MayNarrow1 { 
    type T = SubC 
} 

object Narrowed2 extends MayNarrow1 { 
    type T = SubC 
    override def m(t: T): Unit = t.bar 
} 

Có thể xác định phương pháp m trong MayNarrow1 vì loại T xảy ra trong vị trí contravariant (as type một cuộc tranh luận phương pháp của), do đó nó vẫn còn hiệu lực ngay cả khi T được thu hẹp xuống trong một loại phụ của MayNarrow1 (thân phương pháp có thể xử lý t như thể nó là loại C).

Ngược lại, type T = C không tránh khỏi sửa lỗi T, loại tương ứng với phương thức thực hiện final.Bằng cách sửa chữa T, nó có thể được sử dụng trong một vị trí hiệp biến (như kiểu trả về của phương pháp):

trait Fixed extends MayNarrow1 { 
    type T = C // make that T <: C to see that it won't compile 
    final def test: T = new C {} 
} 

Bạn có thể dễ dàng thấy rằng nó phải được cấm để tiếp tục 'đè' T:

trait Impossible extends Fixed { 
    override type T = SubC 

    test.bar // oops... 
} 

Để được hoàn thành, đây là trường hợp ít phổ biến của một ràng buộc thấp:

trait MayNarrow2 { 
    type T >: SubC // allows covariant positions in MayNarrow2 
    def test: T = new SubC {} 
} 

object Narrowed3 extends MayNarrow2 { 
    type T = C 
    test.foo 
} 

object Narrowed4 extends MayNarrow2 { 
    type T = C 
    override def test: T = new C {} 
} 
+1

Lưu ý: cho sự khác biệt tinh tế giữa các thành viên kiểu trừu tượng với giới hạn so với các tham số kiểu với chú thích phương sai, xem bài đăng của Geoffrey Washburn trong http://scala-programming-language.1934581.n4.nabble.com/Scala-type-override-td1943353 .html –

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