2013-08-06 24 views
6

Nói rằng tôi có:Lý do cú pháp tham số kiểu này không biên dịch là gì?

class Class[CC[A, B]] 
class Thing[A, B <: Int] 
class Test extends Class[Thing] // compile error here 

tôi nhận được lỗi biên dịch:

kinds of the type arguments (cspsolver.Thing) do not conform to the expected kinds of the type parameters (type CC) in class Class. cspsolver.
Thing's type parameters do not match type CC's expected parameters: type C's bounds <: Int are stricter than type B's declared bounds >: Nothing <: Any

Tuy nhiên khi tôi thay đổi mã như vậy mà nó trông như thế này:

class Class[CC[A, B]] 
class Thing[A, B] { 
    type B <: Int 
} 
class Test extends Class[Thing] 

nó biên dịch tốt. Cả hai đều không có chức năng tương đương?

+5

Trong ví dụ cuối cùng, bạn có tham số kiểu 'B' và nhập thành viên' B'. Họ có cùng tên (vì vậy chỉ có một là có thể nhìn thấy), bot họ không giống nhau. – senia

+0

@senia, có trường hợp sử dụng cùng một tên hữu ích không? – huynhjl

+0

@huynhjl: Tôi đoán là không. Nhưng trong một số trường hợp, việc che bóng có ích: bạn có thể sử dụng lại tên. Ngoài ra còn có một số lạm dụng hữu ích một phần của việc che giấu trong trường hợp có liên quan: xem [câu trả lời này] (http://stackoverflow.com/a/17852226/406435). – senia

Trả lời

1

Lý do được đưa ra trong thông điệp trình biên dịch. Trong số Class, bạn mong đợi một số không giới hạn CC, trong khi Thing có giới hạn đối số loại thứ hai phải là <: Int. Một khả năng là để thêm các hạn chế tương tự để Class như trong

class Class[CC[A,B <: Int]] 
class Thing[A, B <: Int] 
class Test extends Class[Thing] 
+0

Nó không rõ ràng với tôi tại sao hạn chế này là tại chỗ, tại sao không thể trình biên dịch hòa giải hai ở giới hạn dưới? –

0

Xây dựng trên giải thích Petr Pudlák của, đây là những gì tôi giả xảy ra: Trình biên dịch cố gắng thống nhất CC[A, B] với Thing[A, B <: Int]. Theo tuyên bố của B trong số CC, B của loại giới hạn trên là Any, được chọn để khởi tạo B. Tuy nhiên, B trong số Thing được mong đợi có một mức ràng buộc loại trên và do đó trình biên dịch không thành công với thông báo lỗi mà bạn nhận được.

Điều này là cần thiết để bảo toàn tính hợp lý của hệ thống kiểu, như được minh họa trong bản phác thảo sau. Giả sử rằng Thing định nghĩa một hoạt động dựa trên thực tế là nó B <: Int, ví dụ:

class Thing[A, B <: Int] { 
    def f(b: B) = 2 * b 
} 

Nếu bạn tuyên bố Class như

class Class[CC[A,B]] { 
    val c: CC 
} 

Test như

class Test extends Class[Thing] { 
    val t: Thing 
} 

mà không trình biên dịch phàn nàn , sau đó bạn có thể thực hiện cuộc gọi sau

new Test().t.f(true) 

rõ ràng là không an toàn.

+0

Tôi không tin rằng bạn có một ví dụ hợp lệ về lý do tại sao "cho phép một ràng buộc kiểu như vậy để biên dịch" sẽ thất bại .. nhưng vì nó thậm chí sẽ không biên dịch nó khó cho tôi để ghim chính xác lý do tại sao nó sai! –

+0

Nhưng tôi sẽ thử anyway: 'def f (b: B) ...' nằm trong ngữ cảnh 'B <: Int'. Vì vậy, tôi không mua nó trong bất kỳ hoàn cảnh nào 'f (đúng) 'có thể có thể biên dịch được. –

+0

Tôi không chắc chắn tôi làm theo lý do tại sao 'new Test(). T.f (true)' sẽ không bị bắt tại thời gian biên dịch. Trong 'Test' không phải kiểu' t' cần kiểu tham số? Và nếu nó không có 'new Test() .'' trả về' Thing [A, B <: Int] ', để trình biên dịch biết' new Test(). Tf' lấy một 'B <: Int' và 'Boolean' không phải là' <: Int'? – eddiemundorapundo

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