Як перевірити, чи дотримується клас принципу Лісков?
Перевірити дотримання принципу Лісков можна, аналізуючи, чи порушує поведінка підкласу очікування, задані базовим класом. Фактично потрібно переконатися, що нащадок не змінює контракт батьківського класу.
Критерії перевірки:
1. Підклас не повинен посилювати вхідні умови (preconditions)
Якщо базовий клас приймає будь-які значення у визначеному діапазоні, нащадок не може вводити додаткові обмеження. Наприклад, якщо базовий метод приймає будь-яке число, нащадок не повинен вимагати, щоб число було тільки додатним.
2. Підклас не повинен послаблювати вихідні умови (postconditions)
Якщо базовий метод гарантує визначений результат (тип, формат, діапазон), нащадок не може давати менш строгі гарантії. Тобто він зобов'язаний виконувати все обіцяне батьківським класом.
3. Інваріанти базового класу повинні зберігатися
Якщо базовий клас гарантує стабільність своїх полів або станів, нащадок не повинен порушувати ці правила. Наприклад, якщо батьківський клас гарантує, що об'єкт завжди лишається «валідним», нащадок не може вводити стани, в яких об'єкт стає «невалідним».
4. Методи підкласу не повинні кидати нові винятки, яких не було в базового класу
Якщо базовий метод не здатен викинути помилку для певних входів, нащадок не має права порушувати це правило. Інакше клієнтський код починає залежати від конкретного типу об'єкта - це порушення LSP.
5. Підклас не повинен змінювати сенс методів базового класу
Головне правило: поведінка методу нащадка повинна бути сумісною за сенсом з поведінкою батьківського класу. Наприклад, якщо метод батьківського класу «додає елемент», нащадок не повинен «замінювати елемент» чи «ігнорувати додавання».
6. При підстановці нащадка замість батьківського класу клієнтський код повинен працювати без перевірок типу
Якщо десь у коді з'являються конструкції:
if isinstance(obj, Child): ...if obj.__class__ == Child:значить, нащадок порушив LSP, і клієнт змушений враховувати, як він працює.
7. Поведінка підкласу не повинна вимагати додаткової інформації, якої не вимагає базовий клас
Якщо базовий метод працює за будь-яких умов, нащадок не повинен вводити залежність від додаткового стану чи контексту.
Підсумок: Клас дотримується LSP, якщо його екземпляр можна підставити в будь-який код, що очікує базовий клас, і програма збереже коректну поведінку - без додаткових перевірок і змін логіки.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.