Является ли получение BinaryTreeNode из GraphNode нарушением принципа подстановки Лискова?

Обсуждение возникает здесь:

Изменение видимости метода в унаследованном классе

вопрос: действительно ли дизайн «BTNode расширяет GraphNode» является нарушением принципа замены Лискова? В качестве «похожего» примера был показан этот случай: ">Является ли получение квадрата из прямоугольника нарушением принципа подстановки Лискова?

но я не могу понять, почему это похоже. Я очень новичок в дизайне, может кто-нибудь объяснить мне, почему (если) это так?


person Malvinka    schedule 26.08.2017    source источник


Ответы (1)


В Является ли получение квадрата из прямоугольника нарушением Лискова Принцип подстановки?, он в основном говорит, что Square не может наследоваться от Rectangle, потому что есть вещи, которые вы можете делать с Rectangles, но не с Squares — устанавливать ширину, отличную от высоты.

Вы не можете наследовать BTNode от GraphNode, потому что, согласно исходному сообщению, на которое вы ссылаетесь, GraphNode имеет метод с именем addChild. BTNode с другой стороны, может иметь только двоих детей. Наследование от GraphNode также наследует метод addChild. Это позволяет вам добавить несколько дочерних элементов в BTNode, с которыми BTNode не может справиться.

Поэтому BTNode не может наследовать от GraphNode, потому что есть вещи, которые можно делать с GraphNode, но нельзя с BTNodes — добавлять несколько дочерних элементов.

Для полноты картины приведем принцип замещения Лискова из Википедии.

Требование к подтипу: Пусть ϕ(x) — доказуемое свойство объектов x типа T. Тогда ϕ ( y ) должно быть истинным для объектов y типа S, где S — подтип T.

Проще говоря,

Если вы можете выполнить действие X с типом T, вы также сможете выполнить действие X с любыми подклассами T.

person Sweeper    schedule 26.08.2017
comment
Разве ограничение количества детей не решит эту проблему? Это можно сделать одним из двух способов: добавив флаг numberOfChildrenRestricion в GraphNode (который показывает, сколько дочерних элементов может иметь данный конкретный graphNode) или переопределив addChild в BTNode, чтобы он не позволял добавлять более двух дочерних элементов (и, например, бросить исключение)? - person Malvinka; 26.08.2017
comment
Если я решу не выводить BTNode из GraphNode, это будет означать переписывание в основном всего кода (но метод addChild) из одного класса в другой - это тоже не кажется разумным... - person Malvinka; 26.08.2017
comment
@Malvinka Мальвинка Нет, у BTNode есть ребенок слева и один справа. Неясно, на какую сторону addChild добавит ребенка. - person Sweeper; 26.08.2017
comment
@Malvinka Вы когда-нибудь думали о том, чтобы сойти с ума и настроить свой addChild, чтобы принять 2 параметра - Node и Position? Не попадайтесь в эту жесткую теорию. Просто подумайте, что общего у ваших объектов, и хороший дизайн придет к вам. - person Janez Kuhar; 26.08.2017
comment
Вы всегда можете наследовать их обоих от класса Node. @Мальвинка - person Sweeper; 26.08.2017