Tengo dos interfaces en Java (versión 8) que son muy similares. No puedo cambiar las interfaces y no puedo cambiar las clases que las implementan.
public interface A {
int get();
}
public interface B {
int get();
int somethingelse();
}
Ahora tengo una función que su implementación se ajusta a ambas interfaces (casi). Quiero que haga algo así:
public int foo((A | B) p) {
int ret = 0;
if (p instanceof B) {
ret = p.somthingelse();
}
return ret + p.get();
}
No quiero usar la inspección porque esta función está en la tubería principal de mi programa. Quiero que tenga un buen rendimiento. ¿Es posible hacer esto en Java?
Editar:
Una solución simple será copiar / pegar foo()
e implementarlo de manera diferente para cada interfaz. Pero, en realidad, foo()
las interfaces son mucho más largas que eso y estoy tratando de evitar la duplicación de código.
get()
en común. Este es, por supuesto, un ejemplo simplificado. En realidad, tienen más funciones en común.public
acceso es redundante para los métodos de interfaz. ¿Y quiso decir eninstanceof
lugar deimplements
?Respuestas:
Desafortunadamente, no hay forma de crear ese tipo de relación retroactiva entre dos tipos no relacionados.
Si puede cambiar
foo()
y sus invocaciones, podría utilizar interfaces funcionales que coincidan con las firmas que invoca en su interiorfoo
. Estoy usandoIntSupplier
aquí, con las correspondientes expresiones lambda usando implementaciones concretas deA
yB
.Digamos que tiene estas implementaciones:
Puedes cambiar
foo
a algo como:Y llámalo de esta manera:
fuente
foo()
para cada interfaz y luego llame a sufoo()
proveedor correspondiente. ¿Desea agregar esto o desea que edite su respuesta?if
lógica debe permanecer dentrofoo()
. Pero sí, definitivamente puedes hacerlo si es apropiado.IntSupplier
sugerencia en esta respuesta. Además,BImpl
(o simplementeB
) no se puede utilizar como una interfaz funcional, dado más de un método abstracto. Además, de un comentario , la afirmación " dos tipos no relacionados " no es cierta. Nitpick:IntSupplier get
no se usa en su código.B
no se usa como una interfaz funcional.b:somethingelse
es una referencia de método paraIntSupplier
en este caso (te sugiero que compiles el código). Y sí,A
yB
son dos tipos completamente ajenos. Y sobre la solución en general, creo que entiendo que te resulta un poco incómodo. Puedo suponer que hay enfoques más precisos, pero no muchos que eviten la refactorización que el OP no puede permitirse.La única forma que puedo imaginar es esta:
fuente
Afaik, Java no admite esto directamente, pero puede crear manualmente un "contenedor de unión de tipo". Algo como esto:
También puede agregar algunas funciones de inspección como
hasSomethingElse()
, si no hay un valor predeterminado apropiado para devolver, como el0
anterior.fuente