В прошлой статье класс Employee полностью перенимал функционал класса Person:
class Person:
def __init__(self, name):
self.__name = name # имя человека
@property
def name(self):
return self.__name
def display_info(self):
print(f"Name: {self.__name} ")
class Employee(Person):
def work(self):
print(f"{self.name} works")
Но что, если мы хотим что-то изменить из этого функционала? Например, добавить работнику через конструктор, новый атрибут, который будет хранить компанию, где он работает или изменить реализацию метода display_info. Python позволяет переопределить функционал базового класса.
Например, изменим классы следующим образом:
class Person:
def __init__(self, name):
self.__name = name # имя человека
@property
def name(self):
return self.__name
def display_info(self):
print(f"Name: {self.__name}")
class Employee(Person):
def __init__(self, name, company):
super().__init__(name)
self.company = company
def display_info(self):
super().display_info()
print(f"Company: {self.company}")
def work(self):
print(f"{self.name} works")
tom = Employee("Tom", "Microsoft")
tom.display_info() # Name: Tom
# Company: Microsoft
Здесь в классе Employee добавляется новый атрибут - self.company, который хранит компания работника. Соответственно метод __init__() принимает три параметра: второй для установки имени и третий для установки компании. Но если в базом классе определен конструктор с помощью метода __init__, и мы хотим в производном классе изменить логику конструктора, то в конструкторе производного класса мы должны вызвать конструктор базового класса. То есть в конструкторе Employee надо вызвать конструктор класса Person.
Для обращения к базовому классу используется выражение super(). Так, в конструкторе Employee выполняется вызов:
super().__init__(name)
Это выражение будет представлять вызов конструктора класса Person, в который передается имя работника. И это логично. Ведь имя работника устанавливается именно в конструкторе класса Person. В самом конструкторе Employee лишь устанавливаем свойство company.
Кроме того, в классе Employee переопределяется метод display_info() - в него добавляется вывод компании работника. Причем мы могли определить этот метод следующим образом:
def display_info(self):
print(f"Name: {self.name}")
print(f"Company: {self.company}")
Но тогда строка вывода имени повторяла бы код из класса Person. Если эта часть кода совпадает с методом из класса Person, то нет смысла повторяться, поэтому опять же с помощью выражения super() обращаемся к реализации метода display_info в классе Person:
def display_info(self):
super().display_info() # обращение к методу display_info в классе Person
print(f"Company: {self.company}")
Затем мы можем вызвать вызвать конструктор Employee для создания объекта этого класса и вызвать метод display_info:
tom = Employee("Tom", "Microsoft")
tom.display_info()
Консольный вывод программы:
Name: Tom
Company: Microsoft
Проверка типа объекта
При работе с объектами бывает необходимо в зависимости от их типа выполнить те или иные операции. И с помощью встроенной функции isinstance() мы можем проверить тип объекта. Эта функция принимает два параметра:
isinstance(object, type)
Первый параметр представляет объект, а второй - тип, на принадлежность к которому выполняется проверка. Если объект представляет указанный тип, то функция возвращает True. Например, возьмем следующую иерархию классов Person-Employee/Student:
class Person:
def __init__(self, name):
self.__name = name # имя человека
@property
def name(self):
return self.__name
def do_nothing(self):
print(f"{self.name} does nothing")
# класс работника
class Employee(Person):
def work(self):
print(f"{self.name} works")
# класс студента
class Student(Person):
def study(self):
print(f"{self.name} studies")
def act(person):
if isinstance(person, Student):
person.study()
elif isinstance(person, Employee):
person.work()
elif isinstance(person, Person):
person.do_nothing()
tom = Employee("Tom")
bob = Student("Bob")
sam = Person("Sam")
act(tom) # Tom works
act(bob) # Bob studies
act(sam) # Sam does nothing
Здесь класс Employee определяет метод work(), а класс Student - метод study.
Здесь также определена функция act, которая проверяет с помощью функции isinstance, представляет ли параметр person определнный тип, и зависимости от результатов проверки обращается к определенному методу объекта.