2013-01-02 25 views
16

Are hai (hợp lệ) giới hạn chung:Có một sự khác biệt giữa các giới hạn chung chung "Enum <T> & Foo" và "Enum <kéo dài Foo?>"

<T extends Enum<T> & MyInterface> 
<T extends Enum<? extends MyInterface>> 

giống nhau không?


Giả sử tôi có một giao diện

interface MyInterface { 
    void someMethod(); 
} 

Và một số enums mà thực hiện nó:

enum MyEnumA implements MyInterface { 
    A, B, C; 
    public void someMethod() {} 
} 

enum MyEnumB implements MyInterface { 
    X, Y, Z; 
    public void someMethod() {} 
} 

Và tôi muốn yêu cầu một thực hiện sử dụng không chỉ là một MyInterface mà còn là nó là một enum. Cách "tiêu chuẩn" là bởi một ngã tư bị ràng buộc:

static class MyIntersectionClass<T extends Enum<T> & MyInterface> { 
    void use(T t) {} 
} 

Nhưng tôi đã phát hiện ra rằng điều này cũng hoạt động:

static class MyWildcardClass<T extends Enum<? extends MyInterface>> { 
    void use(T t) {} 
} 

Với trên, này biên dịch:

public static void main(String[] args) throws Exception { 
    MyIntersectionClass<MyEnumA> a = new MyIntersectionClass<MyEnumA>(); 
    a.use(MyEnumA.A); 
    MyWildcardClass<MyEnumB> b = new MyWildcardClass<MyEnumB>(); 
    b.use(MyEnumB.X); 
} 

Và các ràng buộc hoạt động như và dự định và yêu cầu bởi ở trên cho cả hai trường hợp.

Có sự khác biệt nào giữa hai giới hạn này, nếu có, và là cái nào "tốt hơn" cái kia?

+1

Nếu họ thực sự là lành mạnh, tôi muốn ngã tư vì nó doesn' t sử dụng ký tự đại diện mà cá nhân tôi tìm thấy "ô uế" – Bohemian

Trả lời

4

Trong trường hợp cụ thể này, không có sự khác biệt vì thông số kiểu chính thức của Enums có hiệu quả là kiểu tự. Điều này là do người ta không thể kế thừa từ Enum như vậy:

class MyEnumA extends Enum<MyEnum2> {} 
class MyEnumB implements MyInterface {} 

Vì vậy, có ngữ nghĩa, chúng giống nhau, nhưng chỉ vì nó là Enum.

+0

+1 để trả lời phần xây dựng của câu hỏi và không lãng phí thời gian vào cú pháp "tốt hơn" là gì, cho chúng có cùng giá trị như nhau. –

+0

+1 nhưng bạn cũng không thể mở rộng 'java.lang.Enum', phải không? – Saintali

1

Họ sẽ làm điều tương tự, nhưng tôi sẽ nói T extends Enum<? extends MyInterface> là tiêu chuẩn hơn một chút và do đó tốt hơn, nếu chỉ vì nó thường được nhận biết một cách nhanh chóng và dễ dàng hơn. Nhiều người thậm chí không biết về phần & của thuốc generic.

Bạn cũng có thể tranh luận rằng họ đọc hơi khác nhau. T extends Enum<T> & MyInterface Tôi sẽ đọc là "một enum mà cũng xảy ra là một MyInterface." T extends Enum<? extends MyInterface> Tôi sẽ đọc là "một enum thực hiện MyInterface." Vì vậy, đến mức độ đó, đó là vấn đề sở thích cá nhân; Tôi thích cái sau.

+0

-1 Xin lỗi, nhưng mọi thứ sau mệnh đề đầu tiên là chủ quan và không mang tính xây dựng. –

+2

Câu hỏi của @PaulBellora OP bao gồm câu hỏi, "và là một" tốt hơn "so với câu trả lời khác. Đó vốn dĩ là một câu hỏi chủ quan, do đó có vẻ không công bằng khi cập bến mọi người để trả lời câu hỏi. Downvotes của bạn là tất nhiên của bạn để phân phối, nhưng tôi nghĩ rằng các lý do của bạn chủng SO [gợi ý cho downvotes] (http://stackoverflow.com/privileges/vote-down), vì nó không phải là rõ ràng hoặc có lẽ nguy hiểm không chính xác, và tôi 'd tranh luận nó không cẩu thả hoặc không có nỗ lực mở rộng hoặc. – yshavit

+0

Đây là lần đầu tiên tôi downvoted bạn và tôi hứa tôi nghĩ về nó. Đừng lấy nó cá nhân :) –

2

Vì điều thứ hai dựa trên thực tế đặc biệt là các enums Java được triển khai dưới dạng MyEnum extends Enum<MyEnum>, tôi thích cái đầu tiên không dựa vào các giả định như vậy và nêu rõ ràng buộc của bạn.

3

Như những người khác đã chỉ ra, cả hai cú pháp đạt được cùng giới hạn - và chỉ vì trường hợp đặc biệt của enums, nơi chúng tôi biết T trong Enum<T> phải là loại mở rộng ngay lập tức enum. Vì vậy, trong việc hạn chế những gì T có thể được giải quyết, không có sự khác biệt.

sự khác biệt trong cách sử dụng có thể có của các trường hợp T, nhưng nó có thể là một sắc thái không liên quan.Hãy xem xét rằng các tuyên bố sau biên dịch trong MyIntersectionClass.use nhưng không MyWildcardClass.use:

T t2 = t.getDeclaringClass().newInstance(); 

Chỉ những sẽ biên dịch trong trường hợp sau:

MyInterface t2 = t.getDeclaringClass().newInstance(); 
Enum<? extends MyInterface> t3 = t.getDeclaringClass().newInstance(); 
Các vấn đề liên quan