Существует класс LinkedList с такими функциями, как add_first (), add_last (), add_after (), remove_first (), remove_last () и remove ()
Теперь есть класс Stack, который предоставляет такие функции, как push (), pop (), peek () или top (), и для реализации этих методов он расширяет методы класса LinkedList. Это нарушение принципа подстановки Лискова?
Например, рассмотрим случай add_after () для добавления узла в n-ю позицию связанного списка. Это можно сделать в базовом классе, но не в классе Stack. Постусловия здесь ослаблены, или вы модифицируете метод add_after () для добавления в верхнюю часть стека?
Кроме того, если не нарушение, это плохой дизайн? И как бы вы реализовали функциональность Stack с помощью класса LinkedList?
LinkedList
? Возможно, вы захотите прислушаться к совету некоего Джошуа Блоха (который сыграл главную роль в разработке инфраструктуры коллекций Java), когда он сказал: «Предпочитаю композицию над наследованием». Может быть, естьLinkedList
внутренний класс стека, но на самом деле не расширять его?LinkedList
который выполняет тяжелую работу за кулисами (композиция). Таким образом, пользователи вашего кода не могут случайно использовать стек, где им нужен список, или наоборот.Ответы:
Нет. Прекрасно добавлять методы в подтип.
Это является нарушением LSP. В LSP говорится, что экземпляры подтипа должны быть заменяемыми для экземпляров супертипа без изменения требуемых свойств программы. Если подтип удаляет метод, любой код, вызывающий этот метод, будет аварийно завершен (или получит
NoMethodError
исключение или что-то в этом роде). Ясно, что «не сбой» является желательным свойством.Изменение
add_after()
метода таким способом является нарушением правила истории (самое важное из правил!) И, таким образом, не помогает устранить нарушение LSP.Используя композицию.
ПРИМЕЧАНИЕ. Все, что я написал выше, относится только к языкам, которые путают подтипы и подклассы! LSP - это подтип , а не подкласс. В языке , который не путает два, это было бы вполне приемлемо , чтобы сделать
Stack
подклассLinkedList
, до тех пор , пока вы не сделать его подтип изLinkedList
.источник
Поскольку все уже было рассмотрено Йоргом Миттагом, я просто уточню следующую часть:
В основном, когда возникает вопрос, нарушает ли какая-либо иерархия LSP, это зависит от того, какой контракт вы заключаете. Итак, какой контракт
add_after
имеет? Если это звучит, как бы странно это ни звучало, например, «Добавить узел в n-й позиции или наверху», то все в порядке, постусловие выполнено, LSP не нарушается. В противном случае это нарушение LSP.источник