2011-09-15 19 views
9

tengo le gustaría crear una interfaz:¿Es posible tener un método de interfaz definido con un tipo de devolución genérico y una implementación concreta definir el tipo de devolución?

public interface OperandValue 
{ 
    <T> T getValue(); 
} 

Después me gustaría tener una aplicación concreta de esta manera:

public class NumberOperandValue implements OperandValue 
{ 
    @Override 
    public <Integer> Integer getValue() 
    { 
     // some integer value that is set elsewhere 
     return 1; 
    } 
} 

Eclipse ha subrayado la <Integer> darme una advertencia que dice:

el número entero parámetro de tipo se esconde el tipo Integer

Agradezco cualquier sugerencia sobre si esto puede funcionar de alguna manera. Me doy cuenta de que podría definir el tipo genérico en el nivel de interfaz y no en el nivel de método, pero me gustaría intentar que esto funcione, si es posible.

Respuesta

22

Es posible que desee cambiar la interfaz para:

public interface OperandValue<T> 
{ 
    T getValue(); 
} 

Y la aplicación a:

public class NumberOperandValue implements OperandValue<Integer> 
{ 
    @Override 
    public Integer getValue() 
    { 
     // some integer value that is set elsewhere 
     return 1; 
    } 
} 

Ahora usted está diciendo a la interfaz de qué tipo usted quiere que el método para volver. En otras palabras, está haciendo que el tipo de interfaz sea genérico, en lugar de la declaración del método. Pero eso parece ser lo que quieres.

Como nota al margen:

public <Integer> Integer getValue() 

significa realidad, 'definir un parámetro de tipo genérico con el nombre de 'Entero'' donde getValue devuelve el tipo "Entero" que se acaba de definir.

responder a los comentarios de Steve A continuación:

cuando quito la <Integer> de mi implementación del método que a continuación una advertencia que dice: Type safety: The return type Integer for getValue() from the type NumberOperandValue needs unchecked conversion to conform to T from the type OperandValue

Ese mensaje de advertencia indica que se está rompiendo las reglas cuando usa los genéricos de Java. Para ver por qué, consideremos qué significa la firma del método antes de eliminar el parámetro de tipo <Integer>.

public <Integer> Integer getValue() 

Esta firma significa que el método getValue devuelve un valor de tipo Integer donde Integer se define como el parámetro de tipo genérico se ha definido entre los soportes de ángulo. El significado de la cadena Integer es completamente arbitraria y tendría exactamente el mismo significado que:

public <T> T getValue() 

Para mayor claridad, vamos a seguir con esta versión de la firma del método a los efectos de su pregunta. ¿Qué sucede cuando eliminamos el parámetro de tipo?

public T getValue() 

Ahora bien, si se va a tratar de compilar, se obtendría un error que T no está definido. Sin embargo, debido a que su firma de tipo original, declaró el parámetro de tipo con el nombre Integer cuando se la ha quitado, que se quedaron con:

public Integer getValue() 

Debido a Integer es ya un tipo predefinido, la firma del método sigue siendo técnicamente legales . Sin embargo, es solo un accidente que el nombre de su parámetro de tipo sea el mismo que el que ya existe.

Además, como su interfaz ya declaró una firma de método con genéricos, el compilador de Java genera una advertencia cuando la elimina de la implementación. Específicamente, al compilador le preocupa que en la clase base, el tipo de devolución del método sea el parámetro genérico (type-borrado a Object) llamado Integer, que no es del mismo tipo (ni se sabe que es compatible con el tipo) clase del sistema denominada Integer (o java.lang.Integer para ser precisos).

+0

¿Es posible tener un método de interfaz genérico? Si es así, ¿cómo lo lograrías? – Kal

+1

@Kal, sí, es posible. Pero no es posible "conectar" el tipo específico en una clase de implementación. Si el método es genérico, significa que * la persona que llama * del método es responsable de proporcionar el argumento de tipo. –

+0

Gracias Kirk. Ya veo. Si la definición de la interfaz era la definida por el OP, entonces la implementación debería tener el método definido como '@Override public T getValue()' también. ¿Correcto? – Kal

Cuestiones relacionadas