java - móviles - manual de programacion android pdf
Método de anulación con tipo de devolución genérico (4)
¿Por qué quieres tener algo así como public abstract Class<? extends Interface> getMainClass();
public abstract Class<? extends Interface> getMainClass();
en lugar de public abstract Interface getMainClass();
?
Creo que simplemente puede devolver una instancia de Interface
, y luego, si la persona que llama desea tener acceso a la clase de tiempo de ejecución subyacente, simplemente puede llamar a getClass()
en el objeto devuelto.
Esencialmente, creo que puedes simplemente hacer
public InterfaceImpl implements Interface {
// ...
};
public abstract class A {
public abstract Interface getMainClass();
// ...
}
public class AImpl {
return new InterfaceImpl();
}
public class Main {
public static void main(String[] args) {
AImpl aImpl = new AImpl();
Interface i = aImpl.getMainClass();
System.out.println(i.getClass());
}
}
Digamos que tengo una superclase que define el siguiente método abstracto
public abstract <T extends Interface> Class<T> getMainClass();
Ahora si quiero sobrescribirlo en alguna subclase
public Class<Implementation> getMainClass(){
return Implementation.class;
}
Recibo una advertencia sobre la seguridad del tipo y la conversión sin marcar:
Tipo de seguridad: el tipo de retorno
Class<Implementation>
paragetMainClass()
del tipoSubFoo
necesita conversión sinSubFoo
para cumplir con laClass<Interface>
del tipoSuperFoo
¿La Class<Implementation>
corresponde a la Class<T>
si <T extends Interface>
? ¿Hay alguna manera de deshacerse adecuadamente de la advertencia?
Considere la siguiente situación similar a la suya:
public class SuperFoo {
public abstract <T extends Interface> List<T> getList();
}
public class SubFoo extends SuperFoo {
private List<Implementation> l = new ArrayList<Implementation>();
public List<Implementation> getList() {
return l;
}
public void iterate() {
for (Implementation i: l) ...;
}
}
SubFoo subFoo = new SubFoo();
SuperFoo superFoo = subFoo;
superFoo.getList().add(new AnotherImplementation()); // Valid operation!
subFoo.iterate(); // Unexpected ClassCastException!
En este caso, la advertencia de conversión no verificada le advierte sobre la posibilidad de una ClassCastException
inesperada.
Sin embargo, en su caso, cuando el tipo de devolución es Class<...>
, no es un problema (por lo que yo entiendo), por lo que puede suprimir una advertencia legalmente:
@SuppressWarnings("unchecked")
public Class<Implementation> getMainClass(){ ... }
Otra opción es hacer que SuperFoo
sea genérico:
public class SuperFoo<T extends Interface> {
public abstract Class<T> getMainClass();
}
public class SubFoo extends SuperFoo<Implementation> {
public Class<Implementation> getMainClass() { ... }
}
Para otra opción más (y tal vez la mejor), vea la respuesta de Stas Kurilin.
el tipo de devolución del método predominante debe ser un subtipo del tipo de devolución del método reemplazado.
Class<Impl>
no es un subtipo de la Class<T>
donde <T extends Interface>
. T es desconocido aquí.
Class<Impl>
es un subtipo de Class<? extends Interface>
Class<? extends Interface>
, por reglas de subtipificación.
algunas reglas de subtipado con respecto a los comodines:
para cualquier tipo X
A<X>
es un subtipo deA<? extends X>
A<? extends X>
A<X>
es un subtipo deA<? super X>
A<? super X>
si S
es subtipo de T
A<? extends S>
A<? extends S>
es un subtipo deA<? extends T>
A<? extends T>
A<? super T>
A<? super T>
es un subtipo deA<? super S>
A<? super S>
Más concisamente, ( <:
significa "es un subtipo de")
A<S> <: A<? extends S> <: A<? extends T>
A<T> <: A<? super T> <: A<? super S>
prueba esto
public abstract Class<? extends Interface> getMainClass();
ejemplo reorganizado por tales advertencias java intenta prevenir casos como este
class OtherImpl implements Interface{
}
A a = new B();//where A - your abstract class and B - implementation
Class<OtherImpl> other = a.<OtherImpl>getMainClass();//some broken think, But _without_ runtime exception
Como @axtavt mencionó el ejemplo se rompió. Lo reorganicé