Одним из четырех принципов ООП является наследование (вместе с абстракцией, инкапсуляцием, полиморфизмом).

При создании нового объекта (класса), как в программировании, так и в реальной жизни, мы можем использовать 2 подхода:

  1. Создать экземпляр с нуля.
  2. Использовать уже существующий объект и обработать напильником довести до нужного нам состояния.

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

Возьмем более практический пример. Представим, что перед нами стоит задача запрограммировать класс дерева. Наше дерево имеет следующие атрибуты:  вид, возраст и высоту. Так же дерево обладает способностью расти (при этом будет увеличиваться его высота и возраст) и способностью выводить информацию о себе.

class Tree(object):
     def __init__(self, kind, height):
         self.kind = kind
         self.age = 0
         self.height = height

    def info(self):
         """ Метод вывода информации о дереве """
         print ("{} years old {}. {} meters high.".format(self.age, self.kind, self.height))    

   def grow(self):
        """ Метод роста """
        self.age += 1
        self.height += 0.5

Для проверки создадим экземпляр класса дерево и немного поиграем с ним.

tree_1 = Tree("oak", 0.5)
tree_1.info()
tree_1.grow()
tree_1.info()

наследование в python, python inheritance

Теперь представим, что наша задача усложняется: нам необходимо добавить класс фруктового дерева, у которого будут те же атрибуты и методы, но в дополнение появится метод сбора урожая фруктов. Конечно, мы можем создать с нуля класс FruitTree и переписать наново весь код, который будет практически идентичен тому что мы уже написали, но это будет неэффективно, кроме того, нарушается принцип DRY (Don't Repeat Yourself).  Вместо этого мы можем воспользоваться наследованием, то есть создать класс FruitTree и указать ему в качестве родителя класс Tree. Таким образом, FruitTree получит доступ ко всем атрибутам и методам, которыми обладает класс Tree.

Как указать родительский класс в Python.

Родительский класс помещается в скобки после имени класса.

class FruitTree(Tree):

 Таким образом, наш код для класса фруктового дерева будет следующим:

class FruitTree(Tree):
    def __init__(self, kind, height):
        # Необходимо вызвать метод инициализации родителя.
        # В Python 3.x это делается при помощи функции super()
        super().__init__(kind, height)

    def give_fruits(self):
        print ("Collected 20kg of {}s".format(self.kind))

 Создадим экземпляр класса FruitTree:

tree_2 = FruitTree("apple", 0.7)
# у нас есть доступ к методам родителя
tree_2.info()
tree_2.grow()
# Мы можем использовать свой метод
tree_2.give_fruits()
# А для родительского экземпляра метод give_fruits() недоступен
tree_1.give_fruits() # Вызовет ошибку  

 наследование в python, дочерний класс в python, python inheritance

Зачем использовать наследование.

Концепция наследования в программировании позволяет сократить время разработки, упростить процесс написания программы как сейчас, так и в будущем, когда заказчик захочет внести "небольшие правки" в проект. Правильно спроектированный класс это, кроме прочего, гибкая структура, которую вы свободно сможете изменять, дополнять в будущем. Важно помнить, что иногда проще создать дополнительный базовый класс, наследовать от него и расширять по мере необходимости, чем сразу написать готовый класс.

В нашей следующей статье мы рассмотрим множественное наследование в Python.