Полиморфизм в объектно-ориентированном программировании — это концепция, позволяющая использовать одну функцию или метод для обработки данных различных типов. Хотя имя метода остается постоянным, его реализация изменяется в зависимости от класса, которому он принадлежит. Результаты выполнения такого метода могут быть значительно отличными от класса к классу. Здесь полиморфизм проявляется в разнообразии форм использования одного и того же метода.
Так, у вас может быть два класса с методом с одинаковым названием, например, total, но его реализация будет различна. В классе T1 этот метод прибавляет к аргументу 10, в то время как в классе T2 метод подсчитывает длину строки символов. Метод total в каждом случае выполняет разные действия в зависимости от того, к объекту какого класса он применяется.
class T1: n=10 def total(self, N): self.total = int(self.n) + int(N) class T2: def total(self,s): self.total = len(str(s)) t1 = T1() t2 = T2() t1.total(45) t2.total(45) print(t1.total) # Вывод: 55 print(t2.total) # Вывод: 2
В предыдущих уроках мы уже видели примеры полиморфизма между классами, связанными отношениями наследования. Каждый из них мог иметь собственный метод, как, например, __init__() или square(). Вызываемый метод square() и его действия определяются на основе класса, к которому объект принадлежит.
Стоит отметить, что полиморфизм не ограничивается только наследуемыми классами. Это ключевая составляющая ООП, работающая и без наследования. Классы могут быть не связаны между собой, но при этом иметь одноименные методы, как в нашем случае.
Используя полиморфизм, мы получаем возможность реализации единого интерфейса для работы с объектами разных классов. Например, различные классы могут иметь свои способы вывода данных, но единое название метода позволит обеспечить его стабильное использование в коде, делая программу более ясной.
Полиморфизм в Python проявляется, среди прочего, в методах перегрузки операторов. Например, методы __init__() и __del__() срабатывают при создании и удалении объекта соответственно. Независимо от типа объекта, выполнение операции запускает метод с определенным именем. В случае __init__() это событие связано с созданием объекта.
Обратимся еще раз к примерному применению полиморфизма на примере метода, перегружающего функцию print().
При создании объекта собственного класса и попытке вывести его на экран по умолчанию будет отображена информация о классе и его адрес в памяти. Такое поведение запрограммировано в суперклассе, который наследуется всеми другими.
>>> class A: ... def __init__(self, v1, v2): ... self.field1 = v1 ... self.field2 = v2 ... >>> a = A(3, 4) >>> print(a) <__main__.A object at 0x7f840c8acfd0>
Если вы хотите, чтобы функция print() выводила другую полезную информацию, в классе нужно определить метод
__str__()
. Этот метод обязан возвращать строку, которую и будет выводить print():
class A: def __init__(self, v1, v2): self.field1 = v1 self.field2 = v2 def __str__(self): return str(self.field1) + " " + str(self.field2) a = A(3, 4) print(a)
Вывод:
3 4
Метод __str__()
может возвращать любую строку по вашему выбору. Например, он
может "рисовать" прямоугольник из символов:
class Rectangle: def __init__(self, width, height, sign): self.w = int(width) self.h = int(height) self.s = str(sign) def __str__(self): rect = [] for i in range(self.h): # количество строк rect.append(self.s * self.w) # знак повторяется w раз rect = '\n'.join(rect) # превращаем список в строку return rect b = Rectangle(10, 3, '*') print(b)
Вывод:
********** ********** **********
Практическая работа. Метод перегрузки оператора сложения
Для практики предлагаем вам самостоятельно реализовать перегрузку оператора сложения.
Для этого используется метод __add__(), вызываемый при сложении объектов класса, если он находится с левой стороны в выражении.
Например, в выражении a + b
объект a должен иметь метод __add__().
Объект b может быть любого типа, но чаще это объект того же класса. Он автоматически передается в метод
__add__() как второй аргумент (первый — self).
Также в Python существует правосторонний метод перегрузки сложения - __radd__()
.
Следуя полиморфизму ООП, метод __add__() может возвращать любой результат. Например, его выполнение может быть направлено на молчаливое изменение сущности объекта без явного возврата значений. В вашей программе метод перегрузки сложения может возвращать новый экземпляр того же класса.