resueltos - Java: definición de un miembro que amplía la clase A e implementa la interfaz B
public interface java (2)
Puede declarar parámetros de tipo que tienen límites múltiples, como:
public static <T extends A & B> void test(Class<T> clazz)
Pero no puedes declarar una variable que tiene múltiples límites:
private Class<? extends A & B> variable; // doesn''t work
Puede crear una clase abstract
C
que amplíe A
e implemente B
, de modo que solo se requiera un límite.
abstract class C extends A implements B {}
Entonces:
private Class<? extends C> variable;
Tengo una variable que debe cumplir dos condiciones, y quiero establecerlas en la definición
Sé que puedo definir cualquiera de las condiciones con una variable individual, como en cualquiera de estos ejemplos
private Class<? extends A> variable; //or
private A variable; //or
private Class<? extends B> variable; //or
private B variable;
Pero, ¿hay alguna manera de que la variable cumpla ambas condiciones?
Esperaba algo como esto
private Class<? extends A implements B> variable;
Pero no puedo encontrar ninguna forma de hacerlo sin el encasillado cuando necesito llamarlo o almacenar varias copias de él
Si bien Java no admite directamente tipos de intersección como A&B
, dichos tipos aparecen en límites de parámetros de tipo y conversiones de captura. Podemos expresar A&B
con una capa de abstracción.
public class ValueAB<T extends A&B>
{
public final T v;
// constructor ...
}
public class ClassAB<T extends A&B>
{
public final Class<T> clazz;
// constructor ...
}
En lugar de A&B, Class<? extends A&B>
A&B, Class<? extends A&B>
, usamos envoltorios ValueAB, ClassAB
ClassAB<?> clazz = new ClassAB<>(Foo.class);
ValueAB<?> value = new ValueAB<>(clazz.c.newInstance());
value.v.methodOfA();
value.v.methodOfB();
Esta solución requeriría un contenedor para cada combinación de As y Bs.
Otra solución es usar solo A
como parámetro de tipo vinculado; B
será proporcionado por un comodín vinculado. Esto probablemente sea mejor si necesita expresar múltiples tipos A&B1, A&B2, ...
en el sitio de uso.
public class ValueA<T extends A>
{
public final T v;
...
}
public class ClassA<T extends A>
{
public final Class<T> c;
...
}
---
ClassA<? extends B> clazz = new ClassA<>(Foo.class);
ValueA<? extends B> value = new ValueA<>(clazz.c.newInstance());
Si confunde cómo funciona el comodín en estos casos, vea mi artículo sobre comodines
Una tercera solución está libre de A o B en el sitio de declaración de los contenedores; el sitio de uso proporciona A y B.
public class Value<T extends S, S>
{
public final T v;
...
}
public class Clazz<T extends S, S>
{
public final Class<T> c;
...
}
---
Clazz<? extends A, B> clazz = new Clazz<>(Foo.class);
Value<? extends A, B> value = new Value<>(clazz.c.newInstance());
Sin embargo, esto es probablemente demasiado confuso.