2012-05-17 14 views
45

Tengo el siguiente Clase e Interfaz:argumento de método se extiende clase implementa la interfaz

public class BasicObject{...} 
public interface CodeObject{...} 

Quiero crear un método en el que el argumento de que tenga que ser de tipo BasicObject e implementa CodeObject. Intenté este código, pero no garantiza que clazz sea una clase que implemente CodeObject.

myMethod(Class<? extends BasicObject> clazz){...} 

quiero hacer somethign como este, pero este código no se compila:

myMethod(Class<? extends BasicObject implements CodeObject> clazz){...} 
+0

Esto parece responder a la misma pregunta: http://stackoverflow.com/questions/745756/java-generics-wildcarding-with-multiple-classes – yiannis

Respuesta

61

su patrón tiene clase para extender y ampliar BasicObject/CodeObject poner en práctica (que es en realidad un inter cara). Puede hacerlo con múltiples clases declaradas en la definición de comodín de la firma del método, así:

public <T extends BasicObject & CodeObject> void myMethod(Class<T> clazz) 

Tenga en cuenta que no va a funcionar si lo hace cualquiera de estas maneras:

  • public <T extends BasicObject, CodeObject> void myMethod(Class<T> clazz)

    Esta es la sintaxis técnicamente válida, pero CodeObject no se utiliza; el método aceptará cualquier clase que se extienda a BasicObject, sin importar si extienden/implementan CodeObject.

  • public void myMethod(Class<? extends BasicObject & CodeObject> clazz)
    public void myMethod(Class<? extends BasicObject, CodeObject> clazz)

    Estos son sólo sintaxis incorrecta de acuerdo a Java.

+3

sobre la parte con el "," , ¿cuál es el propósito del "CodeObject"? la clase se extiende desde "BasicObject", pero ¿qué pasa con el "CodeObject"? –

+3

Para mí, funciona solo si uso solo T como tipo de parámetro (sin clase). Línea completa: 'public void myMethod (T clazz)' –

+0

Luego, en el método, ¿cómo puedo llamar a un getter que pertenece a 'BasicObject' en el objeto clazz? – OrangePot

0

Si no todos los BasicObjects implementan CodeObject, a continuación, se puede utilizar un instanceof/Class.isInstance() Llegada su método (ver http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html):

myMethod(Class<? extends BasicObject> clazz) 
{ 
    if (!clazz.isInstance(CodeObject)) 
    { 
     (indicate that the call was incorrect) 
    } 
    ... 
} 
+4

Sí, pero no quiero hacer eso. Por supuesto, cualquier método podría usar myMethod (Object obj) y luego usar 'obj.isInstance (...)', pero eso es lo que trato de evitar. Realmente quiero que los usuarios de mi método se vean obligados a pasar un buen parámetro. – Gab

+0

Bueno, si quieres -force- it podrías bloquear tu programa cada vez que lo hagan (o simplemente lanzar una IllegalArgumentException, estoy seguro de que lo resolverán más rápido de esa manera) – Riking

7

Aquí hay un enfoque que es un poco detallado, pero evita dolores de cabeza genéricos. Crear otra clase que no la extendiendo/aplicación:

public abstract class BasicCodeObject 
    extends BasicObject 
    implements CodeObject {...} 

A continuación, el método puede ser:

public <T extends BasicCodeObject> void myMethod(Class<T> clazz) {...} 
4

Hay dos enfoques para su problema dependiendo de si desea pasar un tipo clase en su argumento de método que extiende BasicObject e implementa CodeObject o un objeto de clase que lo hace. Hay soluciones para ambos.

Solución 1:

Si desea pasar el Class sí, usted puede hacer esto, según lo explicado por @bontade,

public <R extends BasicObject & CodeObject> void myMethod(Class<R> clazz) 

y si desea pasar class objeto, puede escribir

public <R extends BasicObject & CodeObject> void myMethod(R clazz) 

Lo anterior es la forma más compleja que se ocupa de los genéricos.

Solución 2:

La siguiente es la más simple. Se puede definir una clase abstracta que se extiende la clase que desea ampliar y ponerlo en práctica:

public abstract class TargetClassType extends BasicObject implements CodeObject { 

} 

ahora si desea pasar la propia clase, hacer

public void myMethod(Class<TargetClassType> clazz) 

o si desea pasar la objeto de clase, escriba

public void myMethod(TargetClassType clazz) 

Cualquiera de las soluciones anteriores se ajusta a su pregunta, pero la segunda es más simple.

Cuestiones relacionadas