Подтвердить что ты не робот

Проблема с алмазами

Википедия по проблеме алмазов:

"... проблема с алмазом - это двусмысленность, возникающая, когда два класса B и C наследуют от A, а класс D наследуется как от B, так и от C. Если метод в D вызывает метод, определенный в (и не переопределить метод), а B и C переопределили этот метод по-разному, затем из какого класса он наследует: B или C?"

Итак, алмаз выглядит так:

  A
 / \
B   C
 \ /
  D

Мой вопрос: что произойдет, если такого класса нет, но снова B и C объявляют тот же метод, скажем, foo(). Разве это не проблема? Почему это называется проблемой алмазов?

Пример:

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

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

class D extends B, C {
}

new D().foo();
4b9b3361

Ответ 1

Не такая же проблема.

В исходной проблеме метод overriden можно вызвать из A. В вашей проблеме это не может быть так, потому что его не существует.

В проблеме с алмазом столкновение происходит, если класс A вызывает метод Foo. Обычно это не проблема. Но в классе D вы никогда не узнаете, какой экземпляр Foo нужно вызвать:

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

В вашей проблеме нет общего предка, который может вызвать метод. На классе D есть два варианта Foo, на которые вы можете выбрать, но, по крайней мере, вы знаете, что их два. И вы можете сделать выбор между ними.

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

Но, как всегда, вам не нужно многократное наследование. Вы можете использовать aggegration и интерфейсы для решения всех этих проблем.

Ответ 2

В проблеме с алмазом класс D неявно наследует виртуальный метод из класса A. Чтобы вызвать его, класс D вызовет:

A::foo()

Если оба класса B и C переопределяют этот метод, тогда проблема, из которой фактически вызывается.

В вашем втором примере, однако, это не тот случай, когда класс D должен явно состояние, которое вызывалось:

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

Таким образом, проблемы на самом деле не совпадают. В проблеме с алмазом вы не ссылаетесь на производные классы, а на их базовый класс, следовательно, на двусмысленность.

Вот как я это понимаю.

Обратите внимание, что я исхожу из фона С++.