Поліморфізм

Відкрита

8.1 Поліморфізм

Поліморфізм — одна з основних концепцій об'єктно-орієнтованого програмування (ООП), яка дозволяє об'єктам різних класів використовувати один і той же інтерфейс.

У Python поліморфізм досягається через динамічну типізацію та наслідування. Важливим аспектом поліморфізму є перевантаження методів і заміщення методів базового класу методами класу-нащадка.

Основні концепції поліморфізму:

Єдиний інтерфейс для різних об'єктів:

Поліморфізм дозволяє використовувати єдиний інтерфейс для об'єктів різних класів, які можуть мати різну реалізацію методів.

Динамічна типізація:

У Python тип змінної визначається під час виконання, що дозволяє функції працювати з об'єктами будь-якого класу, якщо вони підтримують вимаганий інтерфейс.

Наслідування:

Дозволяє створювати ієрархії класів, де підкласи наслідують властивості та методи базового класу, але можуть перевизначати їх для своєї специфічної функціональності.

Приклади поліморфізму:

Простий приклад поліморфізму: всі три класи мають метод з іменем move(). Це значить, що ми можемо написати код, який буде одночасно працювати з цими об'єктами.

class Car:
    def move(self):
        pass

class Human:
    def move(self):
        pass

class Bird:
    def move(self):
        print("Кар!")

car = Car()
human = Human()
bird = Bird()

for it in [car, human, bird]:
    it.move()

У даному випадку «загальним інтерфейсом» є ім'я методу, ну або його сигнатура, якщо метод має параметри.

8.2 Перевизначення методів

Поліморфізм часто використовується разом з наслідуванням для створення ієрархій класів, де базовий клас визначає загальний інтерфейс, а підкласи реалізують специфічні деталі.

class Employee:
    def get_salary(self):
        return 1000

class FullTimeEmployee(Employee):
    def get_salary(self):
        return 5000

class PartTimeEmployee(Employee):
    def get_salary(self):
        return 3000

class Intern(Employee):
    pass

def print_salary(employee):
    print(employee.get_salary())

employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]

for employee in employees:
    print_salary(employee)

Цей приклад схожий на попередній, але має важливу відмінність — наші класи не зобов'язані мати метод get_salary, адже він завжди є у базового класу. Тепер «загальним інтерфейсом» всіх класів є не просто метод get_salary(), а саме клас Employee зі всіма його методами та атрибутами.

8.3 Виклик методів класу-нащадка

Подивіться уважніше на код нижче:

Ми викликаємо метод print_salary(), який є тільки у базового класу Employee, а він вже з базового класу викликає інший метод базового класу — get_salary(). Які зарплати будуть виведені на екран?

class Employee:
    def print_salary(self):
        salary = self.get_salary()
        print(salary)

    def get_salary(self):
        return 1000

class FullTimeEmployee(Employee):
    def get_salary(self):
        return 5000

class PartTimeEmployee(Employee):
    def get_salary(self):
        return 3000

class Intern(Employee):
    pass

employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]

for employee in employees:
    employee.print_salary()

Важливо! Прочитайте те, що написано нижче — це важливо.

Якщо ми викличемо метод print_salary(), наприклад, у класу FullTimeEmployee, то викликатиметься метод базового класу, так як у самого класу такий метод не оголошений.

Але ось цей метод print_salary() буде викликати метод get_salary() у об'єкта self, який має тип FullTimeEmployee, а не Employee. Тому викликатиметься саме метод get_salary() з класу FullTimeEmployee!

Більше того, клас FullTimeEmployee може викликати метод get_salary() базового класу для своїх потреб. Наприклад, ми хочемо розраховувати зарплату у відсотках від базової ставки:

class FullTimeEmployee(Employee):
    def get_salary(self):
        base_salary = super().get_salary()
        return base_salary * 5






    # 500%


class PartTimeEmployee(Employee):
    def get_salary(self):
        base_salary = super().get_salary()
        return base_salary * 3  # 300%

8.4 Перевантаження методів

Перевантаження методів (method overloading) в Python — це здатність створювати декілька методів з однаковим ім'ям, але різними параметрами. Проте, в чистому вигляді перевантаження методів не підтримується в Python, як це робиться в інших мовах (наприклад, C++ або Java).

У Python можна імітувати перевантаження методів через використання аргументів за замовчуванням, *args і **kwargs.

Приклади перевантаження методів

Ми можемо реалізувати функцію, яка матиме різну поведінку в залежності від кількості переданих аргументів. Зробити це можна різними способами, наприклад, так:

class Example:
    def display(self, a=None, b=None):
        if a is not None and b is not None: print(a, b)
        elif a is not None: print(a)
        else: print("Немає аргументів")


obj = Example()
obj.display(1, 2)  # Output: 1 2
obj.display(1)  # Output: 1
obj.display()  # Output: Немає аргументів

Приклад 2 — враховуємо тип переданих даних

Також можна врахувати тип переданих даних — просто зробити перевірку типу:

class Example:
    def mod(self, a, b):
        if type(a) == int and type(b) == int: print(a % b)
        elif type(a) == float or type(b) == float: print(round(a / b))
        else: print("Інструкція: a та b повинні бути int або float")


obj = Example()
obj.mod(5, 2)  # Output: 1
obj.mod(5.0, 2)  # Output: 2
obj.mod("5", 2)  # Output: Інструкція: a та b повинні бути int або float

Якщо передані неправильні типи даних, можна вивести інструкцію або навіть посилання на документацію в інтернеті — це теж дуже популярне рішення.

2
Задача
Модуль 1: Python Core,  9 рівень,  7 лекція
Недоступна
Поліморфізм.
Поліморфізм.
2
Задача
Модуль 1: Python Core,  9 рівень,  7 лекція
Недоступна
Тваринний світ.
Тваринний світ.
Коментарі (1)
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Дмитро
Рівень 45
10 листопада 2025, 10:40
Який інтерфейс? 😳