Вопрос

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

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

Итак, бриллиант выглядит вот так:

  A
 / \
B   C
 \ /
  D

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

Пример:

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

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

class D extends B, C {
}

new D().foo();
Это было полезно?

Решение

Это не та же самая проблема.

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

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

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

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

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

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

Другие советы

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

A::foo()

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

Однако в вашем втором примере это не так, поскольку классу D потребуется явно указать состояние, которое вызывалось:

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

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

Во всяком случае, так я это понимаю.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top