Несколько абстрактных родителей в ООП в Python
Класс может наследовать сразу от нескольких баз. Если базы абстрактные, потомок должен реализовать все их абстрактные методы - иначе объект такого класса создать нельзя.
Абстрактный метод помечают декоратором
@abstractmethod в модуле abc.
Конкретный класс-потомок обязан дать
ему реализацию.
Давайте попробуем на практике. Пусть кроме
абстрактного класса Figure у нас также
есть абстрактный класс Tetragon.
Методы этого класса будут реализовывать
классы Quadrate и Rectangle,
так как у них 4 стороны, но не класс
Disk.
Пусть класс Tetragon описывает
геттеры для всех четырех сторон
четырехугольника:
from abc import ABC, abstractmethod
class Tetragon(ABC):
@abstractmethod
def get_a(self):
pass
@abstractmethod
def get_b(self):
pass
@abstractmethod
def get_c(self):
pass
@abstractmethod
def get_d(self):
pass
Пусть также у нас есть абстрактный класс
Figure:
from abc import ABC, abstractmethod
class Figure(ABC):
@abstractmethod
def get_square(self):
pass
@abstractmethod
def get_perimeter(self):
pass
Сделаем так, чтобы класс Quadrate
наследовал оба абстрактных родителя.
Для этого перечислим оба класса в скобках:
class Quadrate(Figure, Tetragon):
pass
Доработаем теперь наш класс Quadrate,
чтобы он реализовывал абстрактный класс
Tetragon. Понятно, что наш квадрат
является вырожденным случаем четырехугольника,
ведь у квадрата все стороны равны. Поэтому
все новые методы будут возвращать одно и
тоже - ширину квадрата:
class Quadrate(Figure, Tetragon):
def __init__(self, a):
self.__a = a
def get_a(self):
return self.__a
def get_b(self):
return self.__a
def get_c(self):
return self.__a
def get_d(self):
return self.__a
def get_square(self):
return self.__a * self.__a
def get_perimeter(self):
return 4 * self.__a
Очевидно, что в прямоугольнике уже не все
стороны одинаковы, а только противоположные.
В этом случае новые методы станут немного
отличаться. Ну, и в какой-нибудь трапеции
вообще все 4 стороны будут разные.
Однако, не имеет значения, что за фигуру мы будем рассматривать - важно, что все эти фигуры будут иметь описанные методы (пусть некоторые фигуры и вырожденные) и работать однотипно.
Класс может сочетать обычного родителя
и абстрактную примесь. Пусть мы хотим
сделать класс Programmer на базе
Employee и абстрактного контракта
ProgrammerRole с методами для языков:
from abc import ABC, abstractmethod
class Employee:
def __init__(self, name, salary):
self.__name = name
self.__salary = salary
def get_name(self):
return self.__name
def get_salary(self):
return self.__salary
class ProgrammerRole(ABC):
@abstractmethod
def get_langs(self):
pass
@abstractmethod
def add_lang(self, lang):
pass
class Programmer(Employee, ProgrammerRole):
def __init__(self, name, salary):
super().__init__(name, salary)
self.__langs = []
def get_langs(self):
return self.__langs
def add_lang(self, lang):
self.__langs.append(lang)
Абстрактному родителю все равно, родные методы у класса или унаследованные - главное, чтобы все описанные абстрактные методы были реализованы.
Сделайте так, чтобы класс Rectangle
также наследовал два абстрактных класса:
и Figure, и Tetragon.
Сделайте абстрактный класс Circle
с методами get_radius и
get_diameter.
Сделайте так, чтобы класс Disk также
наследовал два абстрактных класса: и
Figure, и Circle.
Скопируйте код моего класса Employee
и код абстрактного класса ProgrammerRole.
Не копируйте мою заготовку класса
Programmer - не подсматривая в мой
код реализуйте этот класс самостоятельно.