Module (83%)
Section (91%)

Проблема ромба

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


The diamond problem concept

  • есть самый верхний суперкласс с именем A;
  • есть два подкласса, производных от A: B и C;
  • а также самый нижний подкласс с именем D, производный от B и C (или C и B, поскольку эти два варианта означают разные вещи в Python).

Видите ромб?

Посмотрите на код в редакторе. Та же структура, но выраженная на Python.

Некоторые языки программирования вообще не допускают множественное наследование, и, как следствие, они не позволяют построить ромб - это путь, который Java и C# выбрали с момента своего возникновения.

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


Давайте перестроим наш пример с предыдущей страницы, чтобы сделать его более похожим на ромб, как показано ниже:

class Top: def m_top(self): print("top") class Middle_Left(Top): def m_middle(self): print("middle_left") class Middle_Right(Top): def m_middle(self): print("middle_right") class Bottom(Middle_Left, Middle_Right): def m_bottom(self): print("bottom") object = Bottom() object.m_bottom() object.m_middle() object.m_top()

Примечание: оба класса Middle определяют метод с тем же именем: m_middle().

Это вносит небольшую неопределенность в наш образец, хотя мы абсолютно уверены, что Вы можете ответить на следующий ключевой вопрос: какой из двух методов m_middle() действительно будет вызван при выполнении следующей строки?

Object.m_middle()

Другими словами, что Вы увидите на экране: middle_left или middle_right?

Вам не нужно торопиться - подумайте дважды и помните о MRO в Python!

Готовы?

Да, Вы правы. Вызов активирует метод m_middle(), который происходит от класса Middle_Left. Объяснение простое: класс указан перед Middle_Right в списке наследования класса Bottom. Если Вы хотите убедиться, что в этом нет никаких сомнений, попробуйте поменять местами эти два класса в списке и проверьте результаты.

Если Вы хотите получить более глубокие впечатления о множественном наследовании и ромбах, попробуйте изменить наш фрагмент и оснастить класс Upper другим экземпляром метода m_middle(), и внимательно исследуйте его поведение.

Как видите, ромбы могут принести в Вашу жизнь некоторые проблемы - как настоящие, так и те, которые предлагает Python.



Code

class A:
pass


class B(A):
pass


class C(A):
pass


class D(B, C):
pass


d = D()
{{ dockerServerErrorMsg }} ×
{{ errorMsg }} ×
{{ successMsg }} ×