TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
Советы разработчикам (python и не только)

14 Oct 2024, 10:37

Открыть в Telegram Поделиться Пожаловаться

Полиморфизм при наследовании и LSP.

Когда мы строим иерархию объектов, мы часто делаем одноименные методы с разным поведением. Если в родительском классе такой метод отсутствует, то мы в целом вольны в наследниках делать что захотим.

Если же родительский класс содержит такой метод, то у нас есть следующие варианты:

1. Реализация в дочернем классе полностью сохраняет внешнее поведение метода (параметры, результат, побочные эффекты), но отличается реализацией и как следствие нефункциональными характеристиками (например, производительностью). В этом случае классы полностью взаимозаменяемы.
2. Реализация в дочернем классе полностью сохраняет поведение родительского класса, но делает дополнительную работу или меняет поля, отсутствующие в родительском классе. Мы все также можем использовать дочерний класс там, где ожидается родительский, но в других частях программы мы получаем дополнительные возможности.
3. Мы меняем поведение метода родительского класса, но не нарушаем его важные характеристики. В этом случае мы должны четко понимать, какие требования есть к базовому методу, чтобы не нарушить совместимость. Если мы не соблюдаем принцип инверсии зависимости и базовый класс не является абстрактным, может получиться, что требования к методу слишком конкретные и тогда этот вариант фактически сводится к предыдущему. При этом мы можем расширять область значений параметров метода (снимая некоторые ограничения или переходя к родительским типам), а иногда и сужать область значений результата.
4. Мы сохраняем формальные характеристики метода (сигнатуру, возвращаемое значение), но сильно меняем его поведение. Как правило, это происходит когда требования к методу не выделены или по ошибке. В этом случае инструменты, предоставляемые языком программирования, могут предполагать что методы все ещё совместимы, что не является правдой на самом деле.
5. Мы меняем даже сигнатуру метода несовместимым образом. Например, произвольно меняем тип результата или параметров, но не так как в п.3. Класс однозначно нельзя использовать там, где ожидается родительский и это могут обнаружить автоматические инструменты.

Если мы наследуемся от какого-то объекта, согласно принципу подстановки Барбары Лисков (LSP) мы не должны нарушать совместимость. То есть, если в каком-то коде ожидается экземпляр базового класса, а мы туда подставляем дочерний, код должен работать корректно и согласно нашим ожиданиям.

Этот принцип предполагает, что у нас есть определенные требования к поведению нашего кода, сформулированные для базового класса. Они могут быть выражены в документации, а также в виде тестов. Дочерний класс должен полностью соблюдать эти требования и соответственно проходить тесты, причем это относится к поведению объекта на протяжении всей его жизни. Требования не могут быть нарушены даже после вызовов методов дочернего класса, отсутствующих у родителя.

Может показаться, что в точности соблюдая требования, мы лишаемся полиморфизма, однако это не так. Обратите внимание на предложенные выше варианты. (Пример в комментариях)

Таким образом,
• LSP требует совместимости между родительским и дочерними классами на уровне выполнения требований.
• Дочерний объект должен сохранять ожидаемое поведение всегда, после вызова любых методов, включая отсутствующие у родителя.
• Дочерний объект должен проходить тесты, ожидающе экземпляр базового класса
• Использование абстракций позволяет нам добиться большей гибкости при реализации дочерних классов
• Даже при конкретных требованиях у нас есть альтернативные варианты реализации

Дополнительные материалы:
• https://news.mit.edu/2009/turing-liskov-0310
• https://ru.wikipedia.org/wiki/Абстрактный_тип_данных
• https://t.me/advice17/58
• https://en.wikipedia.org/wiki/Dependency_inversion_principle

10k 4 68 39 71
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot