2012-10-10 29 views
9

Với giao diện sau,java thực hiện giao diện chung trong một lớp vô danh

public interface Callback<T> { 
    <K, V> T execute(Operation<K, V> operation) throws SomeException; 
} 

Làm thế nào tôi có thể thực hiện giao diện trong một lớp học vô danh mới, nơi operation là loại Operation<String,String>

ví dụ, điều này không biên dịch:

Callback<Boolean> callback = new Callback<Boolean>() { 
     @Override 
     public Boolean execute(Operation<String, String> operation) { 
       return true; 
     } 
}; 
executor.execute(callback); 
+1

lỗi biên dịch gì bạn nhận được? Tôi có thể thấy rằng hàm của bạn không có câu lệnh trả về, đó là lỗi biên dịch. –

+1

lý do lỗi biên dịch là gì? Và 'SomeException' ở đâu? – mishadoff

+2

Tôi khuyên bạn không nên sử dụng lại tên của bất kỳ lớp học hoặc giao diện phổ biến nào và sử dụng tên khác thay thế. Việc sử dụng lại tên sẽ dẫn đến sự nhầm lẫn như bạn có. –

Trả lời

7

generics trên phương pháp không liên quan đến các lớp thông số chung

bạn cần phải lặp lại chúng trên phương pháp cho nó là đúng, ví dụ

Callback<Boolean> callback = new Callback<Boolean>() { 
     @Override 
     public <X,Y> Boolean execute(Operation<X, Y> operation) { 

     } 
}; 
executor.execute(callback); 

Nói cách khác, giao diện yêu cầu phương thức thực thi hoạt động trên mọi thông số Hoạt động.

Nếu bạn muốn gọi lại chỉ hoạt động trên các thông số cụ thể bạn cần phải đặt chúng thành một phần của chữ ký lớp, ví dụ:

public interface Callback<T,K,V> { 
    T execute(Operation<K, V> operation) throws SomeException; 
} 

mà sau đó sẽ cho phép bạn làm

Callback<Boolean,String,String> callback = new Callback<Boolean,String,String>() { 
     @Override 
     public Boolean execute(Operation<String, String> operation) { 

     } 
}; 
executor.execute(callback); 

Tôi không thể nhìn thấy một con đường để nhận được những gì bạn muốn ... trừ khi bạn bắt đầu sử dụng <? super K,? super V> hoặc <? extends K,? extends V> hình thức mà có thể hạn chế bạn quá nhiều.

Đây là những gì giao diện của bạn xóa để

public interface Callback<T> { 
    T execute(Operation<Object, Object> operation) throws SomeException; 
} 

sau đó khi bạn khởi tạo với T == Boolean chúng tôi nhận

public interface Callback { 
    Boolean execute(Operation<Object, Object> operation) throws SomeException; 
} 

mà không thể được thực hiện bởi một phương pháp

Boolean execute(Operation<String, String> operation) throws SomeException; 

như trong thông số hẹp hơn. Bạn có thể mở rộng trong các tham số và thu hẹp các tham số nhưng bạn không thể đi theo cách khác.

Điều đó giải thích tại sao bạn có thể thay đổi kiểu trả về (trong tham số) Object-Boolean như bất cứ ai mong đợi một Object sẽ được hạnh phúc với một Boolean.

Ngược lại, chúng tôi không thể mở rộng loại trả lại vì điều này sẽ cung cấp cho một ClassCastException cho bất kỳ ai gọi phương thức và hành động trên kết quả.

Đối số phương pháp (trong tham số) chỉ có thể được mở rộng. Bây giờ nó là hơi phức tạp cho các đối số phương pháp như Java thấy loại khác nhau như các phương pháp khác nhau, vì vậy bạn một cách hợp pháp có thể có

public interface Callback<T> { 
    T execute(Object key, Object value); 
} 

Callback<Boolean> cb = new Callback<Boolean> { 
    @Override 
    public Boolean execute(Object k, Object v) { ... } 
    // not an @Override 
    public Boolean execute(String k, String v) { ... } 
} 

vì phương pháp thứ hai có chữ ký khác nhau.Nhưng lớp học Operation<X,Y> của bạn sẽ bị xóa chỉ thành loại thô bất kể đó có phải là số Operation<String,String> hoặc Operation<X,Y>

Có một điều bạn có thể làm ... nhưng nó trở nên lộn xộn!

public interface StringOperation extends Operation<String,String> {} 

sau đó bạn có thể làm

Callback<Boolean> cb = new Callback<Boolean> { 
    @Override 
    public <K,V> Boolean execute(Operation<K,V> o) { ... } 
    // not an @Override 
    public Boolean execute(StringOperation o) { ... } 
} 

nhưng hãy nhớ rằng phương pháp execute(Callback<?>) sẽ gọi <K,V> Boolean execute(Operation<K,V> o) và không Boolean execute(StringOperation o)

5

Vì thông số loại trong tên lớp và thông số loại trong phương pháp thực sự khác nhau Bạn có thể làm phía dưới.

@Override 
    public <K, V> Boolean execute(Operation<K, V> operation) 
      throws SomeException { 
     return false; 
    } 
+0

hoạt động này, nhưng nếu tôi muốn hoạt động sử dụng kiểu generic trong phương thức thực thi bên? – user1735096

+0

Bạn sẽ phải thay đổi 'Gọi lại ' thành 'Gọi lại ' –

+0

cảm ơn. Thật không may trong trường hợp này, đây không phải là một giao diện tôi kiểm soát. – user1735096

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