Полиморфизм является еще одним базовым аспектом объектно-ориентированного программирования и предполагает способность к изменению функционала, унаследованного от базового класса.
Например, пусть у нас будет следующая иерархия классов:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class Person:def __init__(self, name, age):self.__name = name # устанавливаем имяself.__age = age # устанавливаем возраст @propertydef name(self):return self.__name@propertydef age(self):return self.__age@age.setterdef age(self, age):if age in range(1, 100):self.__age = ageelse:print("Недопустимый возраст")def display_info(self):print("Имя:", self.__name, "\tВозраст:", self.__age) class Employee(Person):# определение конструктораdef __init__(self, name, age, company):Person.__init__(self, name, age)self.company = company# переопределение метода display_infodef display_info(self):Person.display_info(self)print("Компания:", self.company) class Student(Person):# определение конструктораdef __init__(self, name, age, university):Person.__init__(self, name, age)self.university = university# переопределение метода display_infodef display_info(self):print("Студент", self.name, "учится в университете", self.university) people = [Person("Tom", 23), Student("Bob", 19, "Harvard"), Employee("Sam", 35, "Google")] for person in people:person.display_info()print() |
В производном классе Employee, который представляет служащего, определяется свой конструктор. Так как нам надо устанавливать при создании объекта еще и компанию, где работает сотрудник. Для этого конструктор принимает четыре параметра: стандартный параметр self, параметры name и age и параметр company.
В самом конструкторе Employee вызывается конструктор базового класса Person. Обращение к методам базового класса имеет следующий синтаксис:
| 1 | суперкласс.название_метода(self [, параметры]) |
Поэтому в конструктор базового класса передаются имя и возраст. Сам же класс Employee добавляет к функционалу класса Person еще один атрибут – self.company.
Кроме того, класс Employee переопределяет метод display_info() класса Person, поскольку кроме имени и возраста необходимо выводить еще и компанию, в которой работает служащий. И чтобы повторно не писать код вывода имени и возраста здесь также происходит обращение к методу базового класса – методу get_info: Person.display_info(self).
Похожим образом определен класс Student, представляющий студента. Он также переопределяет конструктор и метод display_info за тем исключением, что вместо в методе display_info не вызывается версия этого метода из базового класса.
В основной части программы создается список из трех объектов Person, в котором два объекта также представляют классы Employee и Student. И в цикле этот список перебирается, и для каждого объекта в списке вызывается метод display_info. На этапе выполнения программы Python учитывает иерархию наследования и выбирает нужную версию метода display_info() для каждого объекта. В итоге мы получим следующий консольный вывод:
| 1 2 3 4 5 6 | Имя: Tom Возраст: 23 Студент Bob учится в университете HarvardИмя: Sam Возраст: 35Компания: Google |
Проверка типа объекта
При работе с объектами бывает необходимо в зависимости от их типа выполнить те или иные операции. И с помощью встроенной функции isinstance() мы можем проверить тип объекта. Эта функция принимает два параметра:
| 1 | isinstance(object, type) |
Первый параметр представляет объект, а второй – тип, на принадлежность к которому выполняется проверка. Если объект представляет указанный тип, то функция возвращает True. Например, возьмем выше описанную иерархию классов:
| 1 2 3 4 5 6 7 8 | for person in people:if isinstance(person, Student):print(person.university)elif isinstance(person, Employee):print(person.company)else:print(person.name)print() |