Как в ООП смоделировать отношение между классами ‘Человек’, ‘Мужчина’ и ‘Женщина’?

«Как в ООП смоделировать отношение между классами ‘Человек’, ‘Мужчина’ и ‘Женщина’?» — вопрос из категории ООП, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Эта связь моделируется с помощью наследования (Inheritance) — одного из ключевых принципов ООП.

Человек является базовым (родительским) классом, а Мужчина и Женщинапроизводными (дочерними) классами. Это классический пример отношения "is-a" (является): Мужчина является Человеком, Женщина является Человеком.

Дочерние классы получают все атрибуты и методы родительского, но могут их расширять или переопределять.

Пример на Python

class Person:  # Базовый класс
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        return f"Я {self.name}, мне {self.age} лет"

class Man(Person):  # Производный класс
    def __init__(self, name, age, has_beard=False):
        # Вызов конструктора родительского класса для инициализации общих полей
        super().__init__(name, age)
        self.has_beard = has_beard # Расширение - добавление нового атрибута

    def introduce(self):
        # Переопределение метода родителя с использованием его базовой логики
        base_intro = super().introduce()
        beard_status = 'есть' if self.has_beard else 'нет'
        return f"{base_intro}. Я мужчина. Борода: {beard_status}."

class Woman(Person):  # Производный класс
    def introduce(self):
        # Простое переопределение метода
        return f"{super().introduce()}. Я женщина."

# Использование
man = Man("Иван", 30, has_beard=True)
woman = Woman("Анна", 25)

print(man.introduce())
# Вывод: Я Иван, мне 30 лет. Я мужчина. Борода: есть.
print(woman.introduce())
# Вывод: Я Анна, мне 25 лет. Я женщина.

Ключевые моменты в примере:

  • Наследование: Man(Person) означает, что Man наследует от Person.
  • Расширение: Класс Man добавляет новый атрибут has_beard, которого нет в Person.
  • Переопределение (Override): Оба дочерних класса предоставляют свою реализацию метода introduce().
  • Использование super(): Функция super() позволяет обратиться к методам родительского класса, чтобы избежать дублирования кода.