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.publicacceso es redundante para los métodos de interfaz. ¿Y quiso decir eninstanceoflugar 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 usandoIntSupplieraquí, con las correspondientes expresiones lambda usando implementaciones concretas deAyB.Digamos que tiene estas implementaciones:
Puedes cambiar
fooa 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?iflógica debe permanecer dentrofoo(). Pero sí, definitivamente puedes hacerlo si es apropiado.IntSuppliersugerencia 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 getno se usa en su código.Bno se usa como una interfaz funcional.b:somethingelsees una referencia de método paraIntSupplieren este caso (te sugiero que compiles el código). Y sí,AyBson 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 el0anterior.fuente