2012-10-10 32 views
9

Dada la siguiente interfaz,Java implementa la interfaz genérica de una clase anónima

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

¿Cómo iba a implementar la interfaz en una nueva clase anónima donde operation es de tipo Operation<String,String>

por ejemplo, esto no significa compilar:

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

error de compilación Lo qué se obtiene? Veo que su función no tiene una declaración de devolución, que es un error de compilación. –

+1

¿Cuál es el motivo del error de compilación? ¿Y dónde está 'SomeException'? – mishadoff

+2

Sugiero que no vuelva a utilizar el nombre de ninguna clase o interfaz común y use un nombre diferente en su lugar. Reutilizar nombres lleva a confusión como la que tienes. –

Respuesta

7

los genéricos en el método no están relacionados con la clase de parámetros genéricos

necesita repetirlos en el método para que sea correcta, por ejemplo,

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

     } 
}; 
executor.execute(callback); 

En otras palabras, la interfaz requiere un método que funciona en cualquier parámetro de funcionamiento Ejecutar.

Si desea una devolución de llamada que solo funcione en parámetros específicos, debe formar parte de la firma de la clase, p.

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

que luego le permiten hacer

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

     } 
}; 
executor.execute(callback); 

no puedo ver una ruta para conseguir lo que quieres ... a menos que empiece a usar los <? super K,? super V> o <? extends K,? extends V> formas que pueden restringir demasiado.

Aquí es lo que su interfaz borra a

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

a continuación, cuando se ejemplariza con T == Boolean obtenemos

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

que no puede ser implementado por un método

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

como el de los parámetros son más estrechos Puede ampliar los parámetros y reducir los parámetros, pero no puede ir por el otro camino.

Eso explica por qué se puede cambiar el tipo de retorno (parámetro de salida) a partir de Object a Boolean como cualquier persona que espera un Object será feliz con una Boolean.

Por el contrario, no podemos ampliar el tipo de devolución ya que eso daría un ClassCastException a cualquiera que llame al método y actúe sobre el resultado.

Los argumentos del método (en parámetros) solo se pueden ampliar. Ahora bien, es algo complejo para los argumentos del método como se ve en Java diferentes tipos como diferentes métodos, por lo que puede tener legalmente

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) { ... } 
} 

porque el segundo método tiene una firma diferente.Pero la clase Operation<X,Y> se borra a sólo el tipo cruda con independencia de si se trata de una Operation<String,String> o Operation<X,Y>

Hay una cosa que podría hacer ... pero se complica!

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

entonces puede hacer

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

pero tenga en cuenta que el método execute(Callback<?>) estará llamando y no <K,V> Boolean execute(Operation<K,V> o)Boolean execute(StringOperation o)

5

Debido a que el parámetro de tipo en su nombre de clase y el tipo de parámetro en el método en realidad son diferentes Usted puede hacer a continuación.

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

esto funciona, pero ¿qué ocurre si explícitamente quiero que la operación use tipos genéricos en el método de ejecución lateral? – user1735096

+0

Tendrá que cambiar 'Callback ' a 'Callback ' –

+0

gracias. Desafortunadamente en este caso, esta no era una interfaz que controlo. – user1735096

Cuestiones relacionadas