← Назад к вопросам

Что такое subclass?

2.0 Middle🔥 131 комментариев
#DevOps и инфраструктура#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Subclass в Python

Subclass (подкласс) — это **класс, который наследует свойства и методы от другого класса** (называемого parent class или superclass). Наследование — это один из основных принципов объектно-ориентированного программирования (ООП), позволяющий переиспользовать код и строить иерархии классов.

Основной синтаксис

# Родительский класс (parent class, superclass)
class Animal:
    def __init__(self, name: str):
        self.name = name
    
    def make_sound(self):
        return "Some generic sound"

# Подкласс (subclass, child class)
class Dog(Animal):
    pass

# Использование
dog = Dog("Rex")
print(dog.name)           # "Rex"
print(dog.make_sound())   # "Some generic sound"

Dog наследует все методы и атрибуты от Animal.

Переопределение методов (Method Overriding)

Подкласс может переопределить методы родительского класса:

class Animal:
    def __init__(self, name: str):
        self.name = name
    
    def make_sound(self) -> str:
        return "Some generic sound"
    
    def describe(self) -> str:
        return f"This is {self.name}"

class Dog(Animal):
    def make_sound(self) -> str:
        return "Woof!"

class Cat(Animal):
    def make_sound(self) -> str:
        return "Meow!"

class Cow(Animal):
    def make_sound(self) -> str:
        return "Moo!"

# Использование
dog = Dog("Rex")
cat = Cat("Whiskers")
cow = Cow("Bessie")

print(dog.make_sound())   # "Woof!"
print(cat.make_sound())   # "Meow!"
print(cow.make_sound())   # "Moo!"

# Унаследованный метод работает
print(dog.describe())     # "This is Rex"

Вызов методов родительского класса

Можно вызвать метод родителя с помощью super():

class Animal:
    def __init__(self, name: str, age: int = 0):
        self.name = name
        self.age = age
    
    def info(self) -> str:
        return f"{self.name}, age {self.age}"

class Dog(Animal):
    def __init__(self, name: str, age: int, breed: str):
        super().__init__(name, age)  # Вызываем конструктор родителя
        self.breed = breed
    
    def info(self) -> str:
        parent_info = super().info()  # Вызываем метод родителя
        return f"{parent_info}, breed {self.breed}"

# Использование
dog = Dog("Rex", 5, "Labrador")
print(dog.info())  # "Rex, age 5, breed Labrador"

Множественное наследование

Подкласс может наследовать от нескольких родительских классов:

class Swimmer:
    def swim(self) -> str:
        return "Swimming..."

class Flyer:
    def fly(self) -> str:
        return "Flying..."

class Duck(Swimmer, Flyer):
    def quack(self) -> str:
        return "Quack!"

# Использование
duck = Duck()
print(duck.swim())    # "Swimming..."
print(duck.fly())     # "Flying..."
print(duck.quack())   # "Quack!"

MRO (Method Resolution Order)

При множественном наследовании Python использует MRO для определения порядка поиска методов:

class A:
    def method(self):
        return "A"

class B(A):
    def method(self):
        return "B"

class C(A):
    def method(self):
        return "C"

class D(B, C):
    pass

# Просмотр MRO
print(D.mro())  # [<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>]

d = D()
print(d.method())  # "B" (B идёт раньше C в MRO)

Абстрактные классы

Можно создать абстрактный класс, который нельзя инстанцировать, но только наследовать от него:

from abc import ABC, abstractmethod

class Vehicle(ABC):
    @abstractmethod
    def start(self):
        pass
    
    @abstractmethod
    def stop(self):
        pass
    
    def describe(self):
        return "This is a vehicle"

class Car(Vehicle):
    def start(self):
        return "Car started"
    
    def stop(self):
        return "Car stopped"

# Использование
# vehicle = Vehicle()  # TypeError: Can't instantiate abstract class
car = Car()
print(car.start())     # "Car started"
print(car.describe())  # "This is a vehicle"

Проверка наследования

class Animal:
    pass

class Dog(Animal):
    pass

dog = Dog()

# Проверка, является ли dog экземпляром Dog
print(isinstance(dog, Dog))      # True

# Проверка, является ли dog экземпляром Animal (родителя)
print(isinstance(dog, Animal))   # True

# Проверка, является ли Dog подклассом Animal
print(issubclass(Dog, Animal))   # True

# Получение класса объекта
print(type(dog).__name__)  # "Dog"

Практический пример: система ролей

from abc import ABC, abstractmethod
from typing import List

class User(ABC):
    def __init__(self, username: str, email: str):
        self.username = username
        self.email = email
    
    @abstractmethod
    def get_permissions(self) -> List[str]:
        pass
    
    def get_info(self) -> str:
        return f"{self.username} ({self.email})"

class Admin(User):
    def get_permissions(self) -> List[str]:
        return ["read", "write", "delete", "manage_users"]

class Moderator(User):
    def get_permissions(self) -> List[str]:
        return ["read", "write", "delete"]

class Guest(User):
    def get_permissions(self) -> List[str]:
        return ["read"]

# Использование
admin = Admin("john_admin", "john@example.com")
mod = Moderator("jane_mod", "jane@example.com")
guest = Guest("bob", "bob@example.com")

users: List[User] = [admin, mod, guest]

for user in users:
    print(f"{user.get_info()} - Permissions: {user.get_permissions()}")
# john_admin (john@example.com) - Permissions: ['read', 'write', 'delete', 'manage_users']
# jane_mod (jane@example.com) - Permissions: ['read', 'write', 'delete']
# bob (bob@example.com) - Permissions: ['read']

Преимущества наследования

  1. Переиспользование кода — не нужно повторять одинаковый код
  2. Организация — логическая иерархия классов
  3. Полиморфизм — разные подклассы могут переопределять методы
  4. Расширяемость — легко добавлять новые подклассы
  5. Поддержка — изменения в родителе автоматически влияют на детей

Проблемы наследования

  1. Tight coupling — подкласс тесно связан с родителем
  2. Хрупкий базовый класс — изменения в родителе могут сломать детей
  3. Сложность — иерархии могут стать запутанными
  4. Композиция часто лучше — использовать объекты вместо наследования

Composition vs Inheritance

# Плохо: глубокая иерархия
class Engine:
    pass

class Car(Engine):
    pass

class SportsCar(Car):
    pass

# Хорошо: композиция
class Engine:
    def start(self):
        return "Engine started"

class Car:
    def __init__(self, engine: Engine):
        self.engine = engine
    
    def start(self):
        return self.engine.start()

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

Что такое subclass? | PrepBro