2010-02-14 13 views
9

Aquí hay un ejemplo que usa herencia de interfaz múltiple en Java y hay un problema.Java: ¿cómo se llama a esta ambigüedad de herencia múltiple?

Tenga en cuenta que sé completamente por qué hay un problema y este no es el punto de mi pregunta. La pregunta es acerca de cómo nombras esta ambigüedad particular de herencia de interfaz múltiple, si hay un nombre para ella.

Por ejemplo, en C++, la ambigüedad que surge cuando se utiliza herencia múltiple ejecución y no se puede determinar el método a utilizar sobrescrito se llama el "problema de diamante":

http://en.wikipedia.org/wiki/Diamond_problem

Ahora, una vez más, me Sé que este no es el mismo problema aquí: ese no es el punto. El punto es que se ha acuñado un nombre en ese caso anterior.

Y me gustaría saber si existe un nombre para el problema que voy a describir.

He aquí un ejemplo de otro tipo de herencia múltiple, donde una interfaz hereda de otras dos interfaces que tienen una incompatibles tipo de retorno método:

interface A { 
    void a(); 
    Integer c(); 
} 

interface B { 
    void b(); 
    Long c(); 
} 

interface MI extends A, B {...} 

(aviso múltiple herencia de interfaces en el trabajo usando la 'extiende' palabra clave)

no se puede hacer eso, porque:

tipos A y B son incompatibles; tanto definen c() pero con retorno sin relación tipo

se ha acuñado un nombre para describir esa situación?

+0

¿Qué pasa si tienen el mismo nombre, tipos de argumentos, tipos de devolución, pero semántica incompatible diferente? ¿Se incluiría ese caso en su pregunta o no? – curiousguy

Respuesta

3

No estoy seguro de que haya un nombre específico para él, o al menos no parece ser muy común. Es "solo" un problema de la asignación implícita de métodos de interfaz a los métodos de clase; si pudiera tener sobrecargas que difieran solo en los tipos de devolución, tampoco habría ningún problema. Por lo tanto, se reduce a un problema de mapeo de firma/sobrecarga/implícito.

En el libro en línea "Pensando en Java", tampoco hay un nombre para él. http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ310_001.htm

Solo una nota al margen, C# permite implementaciones de interfaz explícitas, lo que soluciona este problema.

+0

¿No se le hace la misma pregunta que a I4 en la sección "Colisiones de nombres cuando se combinan interfaces" de su enlace? Así que supongo que se llama "colisiones de nombres cuando se combinan interfaces". ¿Lo entiendo mal? – MatrixFrog

+2

@MatrixFrog: Sí, pero "colisiones de nombres al combinar interfaces" suena más como una descripción del problema para mí, y no como un nombre "estándar" para el problema. – Lucero

-2

No creo que se haya definido un nombre porque las interfaces en Java no pueden tener implementación de método, por lo que se evita el problema ya que siempre hay una sola implementación para un método específico y por lo tanto no surgirá ninguna ambigüedad.

¿He perdido el punto o está hablando de la variable 'c'?

+0

Sí. te perdiste el punto. lee la pregunta nuevamente – shoosh

+0

... y 'c' no es una variable, ni siquiera un campo ... es un método. – Lucero

+0

@zinc: "sin ambigüedad"? En el ejemplo de código de la pregunta hay una ambigüedad: ¿qué debe devolver la implementación de 'MI.c()'? Entero o largo? –

1

No me cabe duda de que se trata de un problema de herencia múltiple, porque las interfaces simplemente describen bien, la interfaz (un conjunto de métodos que debe definir una clase de implementación) en lugar de cualquier implementación. La extensión de una interfaz con otras interfaces no significa realmente que la subinterfaz herede de la superinterfaz, sino que la subinterfaz es, en esencia, una concatenación de los métodos definidos en las dos.

Si se utiliza una tercera interfaz para extender la subinterfaz y proporciona una declaración de método conflictiva, es esencialmente la misma que si acabara de proporcionar los mismos dos métodos conflictivos en la misma interfaz.

+0

No estoy de acuerdo: Java tiene herencia de interfaz múltiple y en mi pregunta planteé varias veces que se trataba de herencia de interfaz múltiple. Y luego las palabras clave 'extends' se usan específicamente. Entonces, algunos consideran que la herencia de interfaz múltiple es herencia múltiple, porque la implementación, después de todo, es solo un detalle (la implementación no existe en el nivel OOA/OOD, realmente es solo un detalle de OOP). La interfaz C seguramente hereda las abstracciones definidas por A y B y, como traductor de OOD a OOP, todo lo que me interesa son abstracciones, no detalles de implementación. – SyntaxT3rr0r

+0

@Tom: luego, para abordar su segundo punto: es más complicado que simplemente tratar de proporcionar dos métodos conflictivos en la misma clase o interfaz. El ejemplo aquí es el único caso en el que tendrá una interfaz heredando (observe nuevamente la palabra clave 'extends') * de dos abstracciones * que no va a funcionar. En todos los demás casos, siempre puede usar herencia de interfaz múltiple en Java. – SyntaxT3rr0r

+0

No estoy en desacuerdo con ningún punto particular suyo, y soy muy consciente de la capacidad de extensión de interfaz múltiple de Java. Simplemente estaba señalando que "es cómo lo miras". Sé que hay distinciones en un nivel de diseño orientado a objetos. Sin embargo, cuando se llega a ello, ¿cómo (más allá de la semántica, y el hecho de que una clase pueda implementar superinterfaces sin implementar subinterfaces) es una interfaz que se extiende a otra diferente de proporcionar todos los métodos definidos en una interfaz? – Tom

2

Tampoco conozco ningún nombre específico para este problema. Siempre que surgió, se describió en una oración que contenía las palabras incompatibilidad de tipo de devolución en algún momento. También puede llamarlo Map/Set incompatibilty ya que este es uno de los ejemplos más destacados y molestos en las bibliotecas de clases de Java. Hace que sea imposible tener el mismo mapa Implementar clase, así como Establecer o Colección, simplemente porque Map define un método eliminar (Objeto) con un tipo de devolución diferente al de Colección.

public interface Collection<E> extends Iterable<E> { 
    boolean remove(Object o); 
} 
public interface Set<E> extends Collection<E> { 
} 
public interface Map<K,V> { 
    V remove(Object key); 
} 
0

El problema que describes existe en .NET, así como Java, pero tiene una solución simple que hay: el marco .NET permite a una clase práctica un miembro de interfaz utilizando un miembro de la clase con un nombre diferente. Por lo tanto, aunque se requiere que los métodos de clase que implementan dos miembros de interfaz que difieren solo en el tipo de retorno tengan diferentes nombres, eso no excluye su capacidad de implementar miembros de interfaz con el mismo nombre.

Si una interfaz hereda dos interfaces con miembros en conflicto, una clase que implemente la interfaz compuesta puede implementar los miembros como si hubiera heredado las interfaces en conflicto directamente. Los consumidores de la interfaz combinada generalmente no podrán usar los miembros de cualquiera de las interfaces de los componentes sin convertir la referencia a uno de los otros tipos de interfaz, pero el elenco en cuestión se considerará un upcast en lugar de un downcast.

El esquema implementado en .NET funciona muy bien allí. Desafortunadamente, no hay forma de hacer algo similar en Java. No sé si Java graznará si una interfaz hereda otras interfaces con miembros en conflicto, pero si grazna o no en ese punto, no habría forma de producir una clase que pueda implementarlo.