2010-10-16 46 views
6

Như một ví dụ thực tế của các câu hỏi chung về lĩnh vực này, tôi muốn thực hiện phương pháp containsAll trong giao diện Set vớiGiao diện thực hiện với lập luận phương pháp superclasses

public boolean containsAll(Iterable<?> c) { /* ... */ } 

tôi con số này nên được cho phép, kể từ CollectionIterable nghĩa là containsAll sẽ bao gồm yêu cầu giao diện. Tương tự như vậy, nói chung có thể thực hiện các giao diện với các siêu lớp đối số có vẻ như nó sẽ hoạt động.

Tuy nhiên, Eclipse không nói cách nào (chưa thử chỉ javac thẳng lên) - ai đó có thể giải thích lý do cho điều đó không? Tôi chắc chắn có một cái gì đó trong spec đó làm cho nó theo cách nó được, nhưng tôi muốn hiểu động lực cho yêu cầu là tốt. Hoặc tôi thiếu một cái gì đó như Iterable<?> không phải là một siêu lớp của Collection<?>?

Là câu hỏi phụ - tôi tuyên bố hai phương pháp sẽ là phương pháp có ký hiệu Iterable luôn được ưu tiên cho các cuộc gọi với đối số Collection?

Lỗi Eclipse:

Nếu tôi loại bỏ các phương pháp với chữ ký Collection, chỉ cần rời khỏi Iterable một (thấy sau khi lỗi), tôi nhận được như sau:

The type BitPowerSet must implement the inherited abstract method Set<Long>.containsAll(Collection<?>)

Việc thực hiện chính xác con người :

@Override public boolean containsAll(Collection<?> c) { 
    for (Object o : c) if (!contains(o)) return false; 
    return true; 
} 
public boolean containsAll(Iterable<?> c) { 
    for (Object o : c) if (!contains(o)) return false; 
    return true; 
} 
+0

Bạn có thể đăng lỗi mà Eclipse đang cung cấp cho bạn không? Làm việc cho tôi trong IDEA. –

+0

@Nikita: đã được chỉnh sửa. Soooo ... nó có thể chỉ là một điều Eclipse? – Carl

+0

Đây là một cơn ác mộng về thuật ngữ. Tôi chạy trốn khỏi những thử thách như vậy. – skaffman

Trả lời

2

Tôi đoán là tại sao java có hạn chế này là, nói rằng bạn có:

class A { 
    void foo(String s) { ... } 
} 

class B extends A { 
    // Note generalized type 
    @Override void foo(Object s) { ... } 
} 

Bây giờ nếu bạn có class C extends B và nó muốn ghi đè foo, nó không phải là rõ ràng những lập luận gì nó nên dùng.

Nói ví dụ C mở rộng Một trực tiếp tại đầu tiên, trọng void foo(String s), và sau đó nó đã được thay đổi để mở rộng B. Trong trường hợp này ghi đè hiện C của foo sẽ trở thành không hợp lệ vì B foo sẽ có thể xử lý tất cả Object s, không chỉ String s.

+0

ah, đó có vẻ là một lời giải thích hợp lý - mở rộng giao diện sẽ yêu cầu các lớp con duy trì giao diện mở rộng. Tuy nhiên, có vẻ như nó phải được cho phép - thông thường, các lớp con không được phép thu hẹp giao diện. – Carl

+0

Nó cũng có thể làm cho thiết kế của bảng ảo rõ ràng hơn để khẳng định rằng tất cả các phương thức trong nó đều có chữ ký chính xác. Hoặc có thể họ chỉ đơn giản là tìm ra rằng họ có thể làm cho nó hoạt động nếu họ xác định nó đủ, nhưng không thấy một nhu cầu hấp dẫn và bỏ nó ra. – oksayt

+0

Tôi đang thiếu thứ gì đó - ví dụ đó có phải là hoạt động không? Trên chú thích @Override tôi nhận được "Phương thức không ghi đè phương thức từ siêu lớp của nó". – Amalgovinus

5

Vì giao diện bạn đang triển khai khai báo (trừu tượng) phương pháp containsAll(Collection<?>), bạn phải thực hiện nó với chữ ký chính xác này. Java không cho phép bạn thực hiện/ghi đè lên một phương thức với một kiểu tham số rộng hơn so với bản gốc. Đây là lý do tại sao bạn nhận được lỗi mà bạn hiển thị khi bạn nhận xét phương thức của mình với chữ ký Collection.

Bạn không hiển thị lỗi khác mà bạn yêu cầu nhận khi phương pháp không được nhận xét, nhưng tôi đoán nó có thể phải làm điều gì đó với quá tải phương thức không rõ ràng.

+0

Không có lỗi khi phương pháp không được nhận xét. Chỉ khi người có chữ ký 'Bộ sưu tập' là. – Carl

+0

Ngoài ra, bất kỳ thông tin chi tiết nào về lý do tại sao lại xảy ra trường hợp này? Là nó dọc theo dòng của câu trả lời @ oksayt? – Carl

+0

@Carl, bạn có nghĩa là tại sao Java được thiết kế như vậy? Có thể là. –

0

Loại đối số là một phần của chữ ký phương thức để jvm cần một phương thức có cùng chữ ký để tìm ghi đè. Một containsAll (Iterable) sẽ có một chữ ký khác với containsAll (Collection).

Nếu tôi nhớ đúng trình biên dịch phải sử dụng một số cách giải quyết để làm cho generics hoạt động mặc dù giới hạn này.

Để câu hỏi thứ hai của bạn, trình biên dịch sẽ thích đối số Bộ sưu tập vì nó là một loại phụ của Iterable, điều này làm cho phương thức Bộ sưu tập cụ thể hơn so với phương thức Lặp lại.

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