2010-01-14 30 views
19

de Wikipedia sobre el problema de diamantes:diamante

" ... el problema de diamantes es una ambigüedad que surge cuando dos clases B y C heredan de A y de clase D hereda de B y C. Si un método en D llama a un método definido en A (y no anula el método), y B y C han anulado ese método de manera diferente, y luego de qué clase hereda: B o C? "

Así que el diamante tiene el siguiente aspecto:

A 
/\ 
B C 
\/
    D 

Mi pregunta es, ¿qué ocurre si no hay tal clase A, pero de nuevo B y C declaran el mismo método, dicen foo(). ¿No es este el mismo problema? ¿Por qué se llama entonces problema de diamantes?

Ejemplo:

class B { 
    public void foo() {...} 
} 

class C { 
    public void foo() {...} 
} 

class D extends B, C { 
} 

new D().foo(); 
+0

¿sobre qué idioma estás preguntando? –

+4

@Neil El lenguaje de Butterworth no debería importar, ya que se trata más de un problema conceptual. Los lenguajes como C++ lo permiten, pero Java y C# no. –

+0

Y esta es la razón por la cual "herencia múltiple" es una palabra sucia ... – Danail

Respuesta

9

No es el mismo problema.

En el problema original, se puede llamar al método modificado desde A. En su problema, este no puede ser el caso porque no existe.

En el problema de los diamantes, el choque ocurre si la clase A llama al método Foo. Normalmente esto no es problema. Pero en la clase D Nunca se puede saber qué instancia de Foo necesita ser llamado:

  +--------+ 
     | A | 
     | Foo | 
     | Bar | 
     +--------+ 
      /\ 
     / \ 
     / \ 
+--------+  +--------+ 
| B |  | C | 
| Foo |  | Foo | 
+--------+  +--------+ 
      \ /
      \ /
      \/
     +--------+ 
     | D | 
     |  | 
     +--------+ 

En su problema, no existe un ancestro común que se puede llamar al método. En la clase D, hay dos sabores de Foo que puedes elegir, pero al menos sabes que hay dos. Y puedes elegir entre los dos.

+--------+  +--------+ 
| B |  | C | 
| Foo |  | Foo | 
+--------+  +--------+ 
      \ /
      \ /
      \/
     +--------+ 
     | D | 
     |  | 
     +--------+ 

Pero, como siempre, no necesita herencia múltiple. Puede usar aggegration e interfaces para resolver todos estos problemas.

+4

El artículo de Wikipedia habla de llamar a foo() desde D, sin embargo. ¿Y qué hay de llamar a foo en una D desde afuera D como nuevo D(). Foo() (también en mi ejemplo)? – cretzel

6

En el problema de diamante, clase D hereda implícitamente el método virtual de la clase A. Para llamarlo, clase D llamaría:

A::foo() 

Si tanto las clases B y C reemplazar este método, entonces el problema viene de lo que en realidad se llama.

En el segundo ejemplo, sin embargo, este no es el caso ya que la clase D tendría que explícitamente estado que estaba siendo llamado:

B::foo() 
C::foo() 

Así que los problemas no son en realidad la misma. En el problema del diamante, no hace referencia a las clases derivadas, sino a su clase base, de ahí la ambigüedad.

Así es como lo entiendo, de todos modos.

Tenga en cuenta que procedo de un fondo de C++.

+0

No sé C++, pero ¿no sería el mismo problema si llamaras a foo desde el exterior D, digamos D() nuevo foo()? Entonces, el ejemplo sin A también sería problemático, ¿verdad? – cretzel

+0

@cretzel, sí, en ese caso también tienes un problema de colisión de nombres. –

+0

Creo que en la mayoría de los casos el compilador (al menos para C++) dará un error debido a la ambigüedad. Tiene en los compiladores que he usado, no estoy seguro de lo que dice el estándar C++ al respecto. – icabod

Cuestiones relacionadas