Java: colisión de nombres de métodos en la implementación de la interfaz

Resuelto Bhaskar asked hace 14 años • 7 respuestas

Si tengo dos interfaces, ambas bastante diferentes en sus propósitos, pero con la misma firma de método, ¿cómo hago para que una clase implemente ambas sin tener que escribir un solo método que sirva para ambas interfaces y escribir alguna lógica complicada en el método? ¿Implementación que verifica qué tipo de objeto se realiza la llamada e invoca el código adecuado?

En C#, esto se soluciona mediante lo que se denomina implementación de interfaz explícita. ¿Existe alguna forma equivalente en Java?

Bhaskar avatar Apr 08 '10 13:04 Bhaskar
Aceptado

No, no hay forma de implementar el mismo método de dos maneras diferentes en una clase en Java.

Esto puede llevar a muchas situaciones confusas, razón por la cual Java no lo permite.

interface ISomething {
    void doSomething();
}

interface ISomething2 {
    void doSomething();
}

class Impl implements ISomething, ISomething2 {
   void doSomething() {} // There can only be one implementation of this method.
}

Lo que puede hacer es componer una clase a partir de dos clases, cada una de las cuales implementa una interfaz diferente. Entonces esa clase tendrá el comportamiento de ambas interfaces.

class CompositeClass {
    ISomething class1;
    ISomething2 class2;
    void doSomething1(){class1.doSomething();}
    void doSomething2(){class2.doSomething();}
}
jjnguy avatar Apr 08 '2010 06:04 jjnguy

No existe una forma real de resolver esto en Java. Podrías usar clases internas como solución alternativa:

interface Alfa { void m(); }
interface Beta { void m(); }
class AlfaBeta implements Alfa {
    private int value;
    public void m() { ++value; } // Alfa.m()
    public Beta asBeta() {
        return new Beta(){
            public void m() { --value; } // Beta.m()
        };
    }
}

Aunque no permite conversiones desde AlfaBetaa Beta, las conversiones abatidas generalmente son malas, y si se puede esperar que una Alfainstancia a menudo también tenga un Betaaspecto, y por alguna razón (generalmente la optimización es la única razón válida), desea poder para convertirlo a Beta, puede crear una subinterfaz Alfacon Beta asBeta()en él.

gustafc avatar Apr 08 '2010 14:04 gustafc

Si se encuentra con este problema, lo más probable es que se deba a que está utilizando la herencia donde debería utilizar la delegación . Si necesita proporcionar dos interfaces diferentes, aunque similares, para el mismo modelo de datos subyacente, entonces debe usar una vista para proporcionar acceso económico a los datos mediante alguna otra interfaz.

Para dar un ejemplo concreto para el último caso, supongamos que desea implementar ambos Collectiony MyCollection(que no hereda Collectiony tiene una interfaz incompatible). Podría proporcionar funciones a Collection getCollectionView()y MyCollection getMyCollectionView()que proporcionen una implementación ligera de Collectiony MyCollection, utilizando los mismos datos subyacentes.

Para el primer caso... supongamos que realmente desea una serie de números enteros y una serie de cadenas. En lugar de heredar de ambos List<Integer>y List<String>, debe tener un miembro de tipo List<Integer>y otro miembro de tipo List<String>y hacer referencia a esos miembros, en lugar de intentar heredar de ambos. Incluso si solo necesita una lista de números enteros, en este caso es mejor usar composición/delegación en lugar de herencia.

Michael Aaron Safyan avatar Apr 08 '2010 06:04 Michael Aaron Safyan