Абстрактные классы и методы в Python

В этом уроке вы узнаете об абстрактных классах в Python и о том, как их использовать для создания моделей для других классов.

Содержание

Что такое абстрактные классы в Python?

В объектно-ориентированном программировании абстрактный класс в Python — это класс, экземпляр которого невозможно создать. Однако вы можете создавать классы, наследующие абстрактный класс. Обычно абстрактный класс используется для создания модели для других классов.

Аналогично, абстрактный метод — это метод без реализации. Абстрактный класс может включать или не включать абстрактные методы. Python не поддерживает напрямую абстрактные классы. Но он предлагает модуль, позволяющий определять абстрактные классы.

Чтобы определить абстрактный класс, используйте модуль abc (abstract base class). Модуль abc предоставляет вам инфраструктуру для определения абстрактных базовых классов.

Например:

from abc import ABC


class AbstractClassName(ABC):
    pass

Чтобы определить абстрактный метод, используйте декоратор @abstractmethod:

from abc import ABC, abstractmethod


class AbstractClassName(ABC):
    @abstractmethod
    def abstract_method_name(self):
        pass

Пример абстрактного класса Python

Предположим, вам нужно разработать программу расчета заработной платы для компании.

В компании есть две группы сотрудников: сотрудники, занятые полный рабочий день, и сотрудники, работающие на почасовой основе. Сотрудники, работающие полный рабочий день, получают фиксированную зарплату, а сотрудники, работающие с почасовой оплатой, соответственно получают почасовую оплату за свои услуги.

Программа расчета заработной платы должна распечатать ведомость заработной платы, включающую имена сотрудников и их ежемесячную зарплату.

Чтобы смоделировать программу расчета заработной платы объектно-ориентированным способом, вы можете создать следующие классы: «Employee», «FulltimeEmployee», «HourlyEmployee» и «Payroll».

Для структурирования программы мы будем использовать модули, где каждый класс размещается в отдельном модуле (или файле).

Класс «Employee»

Класс «Employee» представляет сотрудников, работающих полный или почасовой рабочий день. Он должен быть абстрактным классом, поскольку есть только сотрудники, работающие полный рабочий день, и сотрудники, работающие с почасовой оплатой, обычных сотрудников не существует.

Класс «Employee» должен иметь свойство, возвращающее полное имя сотрудника. Кроме того, у него должен быть метод расчета зарплаты. Метод расчета заработной платы должен быть абстрактным.

Следующий пример определяет абстрактный класс Employee:

from abc import ABC, abstractmethod


class Employee(ABC):
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @property
    def full_name(self):
        return f"{self.first_name} {self.last_name}"

    @abstractmethod
    def get_salary(self):
        pass

Класс FulltimeEmployee

Класс FulltimeEmployee наследуется от класса Employee. Он предоставит реализацию метода get_salary(). Поскольку штатные сотрудники получают фиксированную зарплату, вы можете инициализировать зарплату в конструкторе класса.

Ниже показан класс FulltimeEmployee:

class FulltimeEmployee(Employee):
    def __init__(self, first_name, last_name, salary):
        super().__init__(first_name, last_name)
        self.salary = salary

    def get_salary(self):
        return self.salary

Класс HourlyEmployee

HourlyEmployee также наследуется от класса Employee. Тем не менее, почасовые сотрудники получают оплату в зависимости от рабочего времени и их ставок. Поэтому вы можете инициализировать эту информацию в конструкторе класса.

Чтобы рассчитать зарплату почасовых сотрудников, необходимо перемножить рабочее время и ставки.

Ниже показан класс HourlyEmployee:

class HourlyEmployee(Employee):
    def __init__(self, first_name, last_name, worked_hours, rate):
        super().__init__(first_name, last_name)
        self.worked_hours = worked_hours
        self.rate = rate

    def get_salary(self):
        return self.worked_hours * self.rate

Класс Payroll

Класс Payroll будет иметь метод, который добавляет сотрудника в список сотрудников и распечатывает расчет заработной платы. Поскольку сотрудники, работающие полный рабочий день и почасовые, используют одни и те же интерфейсы (свойство full_time и метод get_salary()), классу Payroll не нужно их различать.

Ниже показан класс Payroll:

class Payroll:
    def __init__(self):
        self.employee_list = []

    def add(self, employee):
        self.employee_list.append(employee)

    def print(self):
        for e in self.employee_list:
            print(f"{e.full_name} \t ${e.get_salary()}")

Основная программа

Следующий файл app.py использует классы FulltimeEmployee, HourlyEmployee и Payroll для распечатки заработной платы пяти сотрудников.

from fulltimeemployee import FulltimeEmployee
from hourlyemployee import HourlyEmployee
from payroll import Payroll

payroll = Payroll()

payroll.add(FulltimeEmployee('John', 'Doe', 6000))
payroll.add(FulltimeEmployee('Jane', 'Doe', 6500))
payroll.add(HourlyEmployee('Jenifer', 'Smith', 200, 50))
payroll.add(HourlyEmployee('David', 'Wilson', 150, 100))
payroll.add(HourlyEmployee('Kevin', 'Miller', 100, 150))

payroll.print()

Выход:

John Doe         $6000
Jane Doe         $6500
Jenifer Smith    $10000
David Wilson     $15000
Kevin Miller     $15000

Когда использовать абстрактные классы

На практике абстрактные классы используются для совместного использования кода несколькими тесно связанными классами. В программе расчета заработной платы все подклассы класса «Employee» используют одно и то же свойство «full_name».

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *