Python: Погружаясь в классы
Теория: Наследование
В программировании мы часто сталкиваемся с необходимостью создать новый класс, который расширяет или изменяет функциональность уже существующих классов. Эту задачу можно выполнить при помощи наследования классов — одного из ключевых механизмов объектно-ориентированного программирования.
В этом уроке мы рассмотрим, как работает наследование классов, и как его можно применять для создания новых сложных структур и при этом не дублировать код.
Наследование классов
Наследование классов — механизм, который позволяет создавать классы (подклассы) на основе других классов — базовые или суперклассы. Подклассы наследуют структуру базовых классов — получают возможность использовать всё, что определено в базовом классе.
Наследование в Python — сложная система со множеством нюансов и деталей. Мы будем изучать его в несколько этапов на протяжении всего курса.
Рассмотрим наследование на примере структуры HTML. Каждый тег в HTML по своему уникален. Также у них есть общие атрибуты и некоторые другие характеристики. Попробуем отобразить это с помощью иерархии классов:
В этом коде мы определили базовый класс HTMLElement, который представляет общую структуру HTML-элемента. Методы set_attribute и get_attribute устанавливают и получают атрибуты HTML-элемента, а set_text_content и get_text_content работают с текстовым содержимым элемента.
Теперь создадим подкласс HTMLAnchorElement, представляющий тег «a» в HTML, наследуя его от класса HTMLElement:
Здесь мы определили класс HTMLAnchorElement, который наследует все атрибуты и методы класса HTMLElement. Мы также добавили метод __str__, который возвращает строковое представление HTML-элемента.
Наследование записывается так: A(B). Эта запись означает, что класс A наследует класс B.
Теперь посмотрим, как работает наследование:
Внутри HTMLAnchorElement нет определения конструктора, но благодаря наследованию, этот класс имеет доступ ко всем публичным методам и свойствам суперкласса. Python вызывает их автоматически при обращении к ним. В свою очередь, внутри __str__() вызываются методы, которых нет в текущих классах, поэтому они также берутся из родительского класса.
Создание подкласса на основе одного класса является довольно простым процессом. Но что, если возникает необходимость наследовать свойства сразу от нескольких классов? В Python для этих целей существует механизм множественного наследования, который позволяет создавать подкласс на основе нескольких классов.
Цепочка наследования
В отличие от некоторых других языков программирования, наследование классов в Python — одиночное и множественное. То есть в Python можно наследоваться от одного или нескольких классов сразу.
Это свойство языка добавляет гибкости, но также и сложности, особенно, когда у базовых классов есть методы с одинаковыми именами. При этом цепочка наследования может быть сколь угодно глубокой:
Это пример четырех классов, каждый из которых наследуется от предыдущего. Это показывает, что наследование в Python может быть «цепочкой», где каждый новый класс наследует свойства и методы предыдущего.
Когда у нас много классов и сложная структура наследования, может возникнуть вопрос, как определить, к какому классу принадлежит конкретный объект. Для этих целей предоставляются специальные операторы и функции для проверки типов.
Оператор проверки типа
В Python можно использовать оператор isinstance() для проверки принадлежности объекта к определенному классу, учитывая при этом наследование:
Здесь мы создали объект anchor класса HTMLAnchorElement и проверили, является ли он экземпляром класса HTMLElement. Поскольку HTMLAnchorElement наследуется от HTMLElement, функция isinstance() возвращает True.
Для проверки точного класса объекта, мы можем использовать функцию type():
Здесь мы используем функцию type(), чтобы проверить, что класс объекта anchor точно является HTMLAnchorElement.
Подобные проверки могут ограничивать возможность использования полиморфизма. Иногда без них не обойтись, но в большинстве случаев лучше использовать интерфейс объекта.
Выводы
Python предоставляет возможность использовать наследование для создания сложных структур данных и гибкого кода. Однако при множественном наследовании и проверках типов могут возникнуть трудности. Вместо этого, рекомендуется использовать интерфейс объекта, чтобы реализовать принцип полиморфизма и избежать этих проблем.
Рекомендуемые программы
Завершено
0 / 14

