Чем абстрактный класс в Python отличается от обычного

Ответ

Абстрактный класс — это класс, который не может быть инстанциирован (нельзя создать его объект) и предназначен для определения общего интерфейса (контракта) для своих подклассов. Он заставляет дочерние классы реализовывать определенные методы.

Ключевые отличия:

  • Инстанцирование: Нельзя создать объект абстрактного класса напрямую. Объект обычного класса создать можно.
  • Абстрактные методы: Абстрактный класс может содержать методы, помеченные декоратором @abstractmethod, у которых нет реализации. Подклассы обязаны их реализовать, иначе они тоже станут абстрактными.
  • Назначение: Служит в качестве шаблона или контракта для группы классов. Обычный класс представляет конкретную сущность.

Для создания абстрактных классов в Python используется модуль abc (Abstract Base Classes).

Пример:

from abc import ABC, abstractmethod

# Абстрактный класс определяет контракт: "любая фигура должна иметь метод для расчета площади"
class AbstractShape(ABC):
    @abstractmethod
    def area(self) -> float:
        # Нет реализации, только объявление
        pass

# Конкретный класс, реализующий контракт
class Square(AbstractShape):
    def __init__(self, side: float):
        self.side = side

    def area(self) -> float:
        return self.side * self.side

# Другой конкретный класс
class Circle(AbstractShape):
    def __init__(self, radius: float):
        self.radius = radius

    def area(self) -> float:
        return 3.14159 * self.radius ** 2

# Попытка создать экземпляр абстрактного класса вызовет TypeError
# shape = AbstractShape() # -> TypeError: Can't instantiate abstract class...

# Экземпляры дочерних классов создаются успешно
square = Square(5)
circle = Circle(3)

print(f"Площадь квадрата: {square.area()}")
print(f"Площадь круга: {circle.area()}")

Ответ 18+ 🔞

Вот ты сидишь, думаешь, что класс — это просто шаблон для объектов, да? А потом бац — тебе говорят про абстрактный класс. И ты такой: «Чё, блядь? Какой ещё абстрактный?»

А это, сука, такой класс-надзиратель, который сам по себе — пустое место, объект из него не слепишь, это тебе не обычный класс, где можно наштамповать экземпляров, как горячих пирожков. Его задача — стоять над душой у своих наследников и орать: «Реализуй метод, падла! Иначе я тебя абстрактным объявлю!»

Чем он, этот зануда, отличается от нормального класса?

  • Создать объект? Забудь. AbstractShape() — это прям TypeError в лоб, как будто ты пытаешься сварить суп из инструкции к супу. А из обычного класса — пожалуйста, хоть сто экземпляров.
  • Абстрактные методы: Вот где его главная фишка, блядь. Он может объявлять методы с декоратором @abstractmethod, у которых тела нет — одна заглушка pass. И все его дети обязаны эти методы написать по-человечески. Не напишешь — будешь вечным абстрактным неудачником.
  • Смысл жизни: Быть этаким ебучим контрактом, шаблоном для целой семьи классов. Говорит: «Все вы, мои потомки, должны уметь считать площадь!» А обычный класс — он просто существует, как конкретная сущность.

В Питоне для этого цирка есть специальный модуль abc (Abstract Base Classes), чтоб ты знал.

Смотри, как это выглядит в коде, чтоб не быть, как Герасим, который только «Му-му» мычит:

from abc import ABC, abstractmethod

# Вот он, наш абстрактный надзиратель. Говорит: "Любая фигура — должна площадь считать!"
class AbstractShape(ABC):
    @abstractmethod
    def area(self) -> float:
        # Реализации нет, епта! Только приказ сверху.
        pass

# Конкретный класс-исполнитель. Квадрат, блядь.
class Square(AbstractShape):
    def __init__(self, side: float):
        self.side = side

    def area(self) -> float:  # Обязан реализовать! Иначе абстрактным останешься.
        return self.side * self.side

# Ещё один работяга. Круг.
class Circle(AbstractShape):
    def __init__(self, radius: float):
        self.radius = radius

    def area(self) -> float:  # Реализовал — молодец, можешь жить.
        return 3.14159 * self.radius ** 2

# Попробуй создать объект абстрактного класса — получишь по ебалу от интерпретатора.
# shape = AbstractShape() # -> TypeError: Can't instantiate abstract class... (Не могу, блядь!)

# А вот из нормальных, послушных классов — пожалуйста, создавай.
square = Square(5)
circle = Circle(3)

print(f"Площадь квадрата: {square.area()}")  # Работает!
print(f"Площадь круга: {circle.area()}")    # Тоже работает!

Вот и вся магия, ёпта. Создал контракт — заставил всех потомков его выполнять. А то разведутся тут классы, которые нихуя не умеют.