Абстрактные классы и методы
Часть раздела Object Oriented Programming путешествия по Python на Coddy — урок 25 из 64.
Абстрактные классы — это классы, экземпляры которых нельзя создать напрямую, и которые содержат абстрактные методы, обязательные для реализации в подклассах.
Представьте это в виде формы: Абстрактный класс похож на шаблон обязательной формы, где некоторые поля обязательны для заполнения (абстрактные методы), а некоторые — нет (конкретные методы). Вы не можете отправить саму форму — сначала нужно заполнить все обязательные поля. Аналогично, вы не можете создавать экземпляры абстрактного класса до тех пор, пока все абстрактные методы не будут реализованы в подклассе.
Импортируйте модуль abc для создания абстрактных классов:
from abc import ABC, abstractmethodСоздайте абстрактный класс с абстрактными методами:
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return "This is a shape" # Конкретный метод (имеет реализацию)Декоратор @abstractmethod помечает методы, которые обязательно должны быть реализованы подклассами — это «обязательные поля» в вашей форме. Обычные методы, такие как describe(), могут иметь реализации и наследуются как есть — это «предварительно заполненные поля».
Зачем использовать абстрактные классы? Они обеспечивают соблюдение контракта. Если вы создаете класс Shape, вы утверждаете, что «каждая фигура ДОЛЖНА уметь вычислять свою площадь и периметр». Это предотвращает ошибки, при которых вы можете забыть реализовать критически важные методы.
Попробуйте создать экземпляр абстрактного класса:
# Это вызовет ошибку:
# shape = Shape() # TypeError: Can't instantiate abstract classЭта ошибка преднамеренна — это всё равно что пытаться отправить пустую форму. Python говорит: «Вы еще не заполнили обязательные поля (методы area и perimeter)!»
Создайте конкретный подкласс, который реализует все абстрактные методы:
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radiusТеперь мы «заполнили все обязательные поля» — мы реализовали как area(), так и perimeter(). Класс Circle теперь является полным, конкретным классом, экземпляр которого можно создать.
Теперь вы можете создавать экземпляры конкретного класса:
circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe()) # Наследуемый конкретный методСоздайте еще один конкретный подкласс:
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width self.height
def perimeter(self):
return 2 * (self.width + self.height)
rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())Вывод:
78.5
31.400000000000002
This is a shape
24
20Абстрактные классы определяют контракт, которому должны следовать подклассы. Используйте ABC и @abstractmethod для создания абстрактных классов. Подклассы должны реализовать все абстрактные методы, иначе они также будут абстрактными. Это обеспечивает согласованность и предотвращает неполные реализации.
Задание
СреднеВ этом испытании вы реализуете систему обработки платежей.
Вам необходимо завершить реализацию в следующих файлах:
paymentmethod.py— абстрактный базовый класс с логикой валидацииcreditcard.py— реализация оплаты кредитной картойpaypal.py— реализация оплаты через PayPal
Следуйте комментариям TODO в каждом файле, чтобы реализовать необходимую функциональность. Комментарии шаг за шагом проведут вас через создание абстрактных методов, реализацию конкретных подклассов и установку правильных связей импорта между файлами.
Файл driver.py содержит тестовые случаи, которые проверят правильность вашей реализации, обрабатывая различные сценарии оплаты и отображая соответствующие детали для каждого метода оплаты.
Шпаргалка
Абстрактные классы не могут быть инстанцированы напрямую и содержат абстрактные методы, которые должны быть реализованы подклассами.
Импортируйте модуль abc:
from abc import ABC, abstractmethodСоздайте абстрактный класс с абстрактными методами:
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return "This is a shape" # Конкретный метод (имеет реализацию)Декоратор @abstractmethod помечает методы, которые должны быть реализованы подклассами. Обычные методы могут иметь реализации.
Абстрактные классы не могут быть инстанцированы:
# Это вызовет ошибку:
# shape = Shape() # TypeError: Can't instantiate abstract classСоздайте конкретные подклассы, которые реализуют все абстрактные методы:
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
circle = Circle(5)
print(circle.area()) # 78.5
print(circle.describe()) # Унаследованный конкретный методКлючевой момент: Абстрактные классы определяют шаблон, которому должны следовать подклассы. Подклассы должны реализовать все абстрактные методы, иначе они также будут абстрактными.
Попробуйте сами
from creditcard import CreditCard
from paypal import PayPal
# Тестирование реализаций - НЕ ИЗМЕНЯЙТЕ ЭТОТ ТЕСТОВЫЙ КОД
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")
# Обработка корректных платежей
if cc.validate(100):
print(cc.process_payment(100))
print(cc.payment_details())
if pp.validate(200):
print(pp.process_payment(200))
print(pp.payment_details())
# Попытка оплаты с некорректной суммой
if not pp.validate(0):
print("Invalid payment amount")
# Это вызвало бы ошибку, если бы было раскомментировано:
# pm = PaymentMethod() # Невозможно создать экземпляр абстрактного классаВ этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыПараметр selfМетодыАтрибутыМетод-конструктор (__init__)Повторение — Простой калькулятор4Наследование
Базовое наследованиеФункция super()Переопределение методовМножественное наследованиеПорядок разрешения методовИтоги — Иерархия сотрудников7Специальные методы
Введение в магические методыПерегрузка операторовМагические методы контейнеровПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy5Полиморфизм
Снова о переопределении методовУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовИтоги — Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияМиксиныСтатические методы и методы классаДекораторы классовМенеджеры контекста11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Свойства классов
Переменные экземпляра и классаДекораторы свойствПриватные атрибутыИтоги — Менеджер банковского счета6Инкапсуляция
Public, Protected, Private члены классаМодификаторы доступаСокрытие данныхДекораторы property: продвинутый уровеньИтоги: Система учета студентов12Проект: Управление библиотекой
Обзор проектаКлассы Book и User