Python ООП: Наследование, инкапсуляция, полиморфизм

Наследование

Наследование — важнейшая концепция объектно-ориентированного программирования (ООП). Любой класс может иметь класс-наследник, который наследует все от родительского класса (суперкласса). Класс-наследник строится на основе родительского и наследует его методы, поля и конструкторы.

Рассмотрим пример: основной класс Building описывает общие характеристики строений: год постройки (year) и город (city).

class Building:
    def __init__(self, year, city):
        self.year = year
        self.city = city

    def get_info(self):
        print(f"Год постройки: {self.year}, город: {self.city}")

school = Building(2000, "Москва")
school.get_info()

Добавление новых функций для каждого типа строения (школа, дом, магазин) в класс Building сделает код нечитабельным и сложным для понимания. Эффективнее создать отдельные классы-наследники.

Создадим класс School, наследующий от Building:

class School(Building):
    pass

school = School(2000, "Москва")
school.get_info()

Класс School наследует все характеристики и методы из Building. Аналогично можно создать классы House и Shop.

class House(Building):
    pass

class Shop(Building):
    pass

Добавим специфические характеристики для каждого класса-наследника. Например, для School добавим количество учеников (pupils):

class School(Building):
    def __init__(self, pupils, year, city):
        self.pupils = pupils
        super().__init__(year, city) # Вызов конструктора родительского класса

    def get_info(self):
        super().get_info()
        print(f"Количество учеников: {self.pupils}")

school = School(100, 2000, "Москва")
school.get_info()

Обратите внимание на использование super().__init__(year, city) для вызова конструктора родительского класса и передачи ему необходимых параметров. В Python множественное наследование не поддерживается — класс может наследовать только от одного родительского класса. Однако, класс-наследник может сам иметь классы-наследники.

Полиморфизм

Полиморфизм позволяет переопределять методы, объявленные в родительском классе, в классах-наследниках. В нашем примере метод get_info() в классе School переопределен для вывода дополнительной информации о количестве учеников. При вызове get_info() для объекта класса School будет использован переопределенный метод, а для объектов других классов — метод из родительского класса.

Инкапсуляция

Инкапсуляция — это защита данных. В Python инкапсуляция реализована не очень строго. Хотя можно использовать двойное подчеркивание (__) перед именем поля для ограничения доступа, это не гарантирует полную защиту.

class Building:
    def __init__(self, year, city):
        self.__year = year # Попытка инкапсуляции
        self.city = city

    def get_year(self):
        return self.__year

building = Building(2023, "New York")
print(building.city) # Доступ к полю city разрешен
print(building.get_year()) # Доступ к полю __year через метод get_year
#print(building.__year) # Прямой доступ к полю __year всё ещё возможен

Хотя прямого доступа к полю __year можно избежать, используя метод get_year(), полная защита данных в Python не гарантируется.

Рассмотрены наследование, полиморфизм и инкапсуляция — ключевые концепции ООП в Python. Наследование позволяет создавать иерархию классов, полиморфизм обеспечивает гибкость в работе с методами, а инкапсуляция (хотя и не очень строго в Python) помогает защитить данные.

Что будем искать? Например,программа