2013-03-29 18 views
5

tôi đã hệ thống phân cấp sau đây trong java:Override trong giao diện kế thừa với kiểu phụ với Generics

interface ObserverA {} 

interface A { 
    void method1(); 
    addObserver(Observer o); 
} 

Và tôi muốn mở rộng nó như thế này:

interface ObserverB extends ObserverA{} 

interface B extends A { 
    void method2(); 
    addObserver(ObserverB o); 
} 

theo một cách như vậy mà addObserver() phương pháp B sẽ ghi đè phương thức tương tự trong A. Vì nó không hoạt động, việc triển khai B sẽ cần phải triển khai cả hai phiên bản addObserver(), tôi không chỉ có một phiên bản.

này có thể được thực hiện trong một cách khéo léo mà không liên quan đến việc phải parameterize A như:

interface A<O extends Observer> { 
    addObserver(O o); 
} 

giải pháp hackish được hoan nghênh nhất!

+0

Kiểu chung luôn là cách tốt hơn để thực hiện những điều như vậy mà bạn không biết loại – Biswajit

Trả lời

1

Làm thế nào về -

interface ObserverA {} 

interface A { 

    <T extends ObserverA> void addObserver(T o); 
} 

và -

interface ObserverB extends ObserverA{} 

interface B extends A{ 

    // do nothing, or omit this interface entirely. 

} 

để bạn sẽ có thể vượt qua bất kỳ loại mà được thừa hưởng ObserverA như là đối số cho phương thức addObserver.

Nếu bạn đang tìm kiếm một chút giải thích, hãy đọc tiếp.

Tôi đã thay đổi phương thức trong giao diện đầu tiên để sử dụng Bounded Type Parameter. Cách nó được khai báo, nó sẽ cho phép bất kỳ đối tượng nào được chuyển làm đối số cho phương thức addObserver miễn là nó là loại ObserverA hoặc nó được kế thừa từ ObserverA. Vì số ObserverB của bạn được kế thừa từ ObserverA, bạn có thể chuyển an toàn đối tượng của cả hai loại ObserverAObserverB vào phương thức này làm đối số.

EDIT

Từ làm rõ của bạn, có vẻ như bạn nên tạo hai giao diện khác nhau mà không bất kỳ mối quan hệ thứ bậc giữa chúng. Chúng dường như không liên quan bởi vì bạn muốn cung cấp các triển khai chỉ cho phương thức thứ hai, trong khi tránh phương thức thứ nhất. Vì vậy, thay vì buộc bản thân phải cung cấp việc triển khai cho phương thức từ giao diện đầu tiên, bạn nên tách chúng ra. Ngoài ra còn có một nguyên tắc OOP cho việc này - Interface Segregation Principle.

+0

Tôi đã thử rằng, vấn đề là 'B' sẽ chấp nhận bất kỳ' 'và tôi muốn nó chỉ chấp nhận 'ObserverB' (hoặc' 'cho vấn đề đó) – Chirlo

+0

@Chirlo: Xem chỉnh sửa của tôi. –

+0

Ví dụ tôi đưa ra là một phiên bản đơn giản của những gì tôi muốn làm. 'A' sẽ là một giao diện phức tạp hơn mà' B' cần mở rộng, nhưng các nhà quan sát của nó cũng phức tạp hơn so với giao diện 'A'. Tôi đã chỉnh sửa câu hỏi để phản ánh thực tế là 'B' mở rộng chức năng từ 'A' – Chirlo

2

Mặc dù ví dụ của bạn cho thấy một cái gì đó khác nhau, tôi cho rằng bạn muốn đạt được một giao diện chung được triển khai bởi các lớp khác nhau. Hãy xem điều này:

public interface Observer<T> { 
    void addObserver(T t); 
} 

public class First implements Observer<First> { 
    @Override 
    public void addObserver(First t) { 
    } 
} 

public class Second implements Observer<Second> { 
    @Override 
    public void addObserver(Second t) { 
    } 
} 

Như bạn có thể thấy cả lớp Đầu tiên và thứ hai triển khai cùng một giao diện nhưng với các loại tham số khác nhau. Họ parametrize giao diện thực hiện với themselved, nhưng thay vì viết Observer<Frist> bạn có thể viết Observer<Integer> hoặc bất cứ điều gì bạn muốn.

EDIT

Đi vào tài khoản của bạn làm rõ đây sẽ là một việc thực hiện chung của mã của bạn trong hệ thống phân cấp giao diện bạn trình bày.

interface ObserverA {} 

interface A<T> { 
    void method1(); 
    void addObserver(T o); 
} 

interface ObserverB extends ObserverA {} 

interface B extends A<ObserverB> { 
    void method2(); 
} 
4

Bạn không thể thu hẹp loại tham số phương thức trong giao diện con hoặc lớp con. Bạn chỉ có thể mở rộng chúng, vì việc triển khai loại phụ phải có khả năng thực hiện hợp đồng của siêu kiểu.

Tương tự, bạn có thể thu hẹp các loại trả lại và ngoại lệ, nhưng không mở rộng các loại trả lại đó, vì cùng một lý do.