Узнайте, когда класс должен наследовать от другого класса.

Я встречал довольно много студентов, которые только начинали изучать объектно-ориентированное программирование (ООП) и были в замешательстве, когда класс должен наследоваться от другого класса. Таким образом, эта статья призвана сделать это как можно более ясным.

Когда использовать наследование (отношение Is-A)

Рассмотрим следующие классы:

  • Животное
  • Млекопитающее
  • Собака
  • Пудель

Основываясь на наших общих знаниях, мы знаем, что:

  • Млекопитающее — это животное (но животное может не быть млекопитающим)
  • Собака — это млекопитающее (но млекопитающее может не быть собакой)
  • Пудель — это собака (но собака может не быть пуделем)

Здесь отношение is-a преобразуется в наследование.

  • Млекопитающее является Животным → Животное является родительским классом, а Млекопитающее является дочерним классом → Млекопитающее наследуется от Животного
  • Собака являетсямлекопитающим → Млекопитающее — это родительский класс, а Собака — дочерний класс → Собака наследуется от млекопитающего
  • Пудель являетсясобакой → собака является родительским классом, а пудель является дочерним классом → пудель наследуется от собаки

Пример реализации

class Animal():
    # stuff
class Mammal(Animal):
    # stuff
class Dog(Mammal):
    # stuff
class Poodle(Dog):
    # stuff

Здесь класс Mammal наследуется от класса Animal, поэтому класс Animal заключен в скобки в определении класса Mammal. То же самое для Dog и Mammal, и Poodle и Dog.

Когда не следует использовать наследование (имеет связь)

Отношение имеет часто ошибочно интерпретируется как наследование. Рассмотрим следующие классы:

  • Компания
  • Отделение
  • Сотрудник

Основываясь на наших общих знаниях, мы знаем, что:

  • В компании много отделов (но отдел не является компанией)
  • В отделе много сотрудников (но сотрудник не является отделом)

Здесь отношение has-a не преобразуется в наследование. Департамент не должен наследовать от Компании, а Сотрудник не должен наследовать от Департамента.

Пример реализации

class Company():
    def __init__(self):
        self.departments = []
class Department():
    def __init__(self):
        self.employees = []
class Employee():
    # stuff

Здесь обратите внимание, что Department не наследуется от Company — вместо этого Company имеет атрибут departments, который представляет собой список, содержащий множество объектов Department. Точно так же Employee не наследуется от Department. Вместо этого Department имеет атрибут employees — список, содержащий множество Employee объектов.

Дополнительные примеры

Форма и треугольник

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

class Shape():
    # stuff
class Triangle(Shape):
    # stuff

Пользователь и ПремиумПользователь

Здесь премиум-пользователь являетсяпользователем (более конкретной версией пользователя), поэтому мы знаем, что PremiumUser должен наследоваться от класса User.

class User():
    # stuff
class PremiumUser(User):
    # stuff

Класс и математический класс

Здесь Класс относится к классу, который учащиеся посещают для изучения материала, а не к концепции программирования. MathClass здесь являетсяклассом (более конкретной версией Class), поэтому мы знаем, что MathClass должен наследоваться от класса Class.

class Class():
    # stuff
class MathClass(Class):
    # stuff

Математический класс и ученик

Здесь мы знаем, что в математическом классе много учеников. MathClass имеет много Students, и аналогично объект MathClass имеет много объектов Student. Однако Student не являетсяMathClass, поэтому здесь не происходит наследования.

class MathClass():
    def __init__(self, stuff):
        self.stuff = stuff
        self.students = [] # list of Student objects
class Student():
    # stuff

Родитель (человек) и ребенок (человек)

Здесь класс Родительский относится к человеческому родителю (мама/папа), а класс Дочерний относится к ребенку-человеку. Как ни странно, здесь не происходит наследования! Человеческий дочерний элемент не являетсячеловеческим родителем, а дочерний элемент не является более конкретной версией родителя. Поэтому класс Child не наследуется от класса Parent! (хотя ребенок в реальной жизни может унаследовать что-то от своих родителей)

# A long-winded example
class Parent():
    def __init__(self, name):
        self.name = name
        self.children = []
class Child():
    def __init__(self, name):
        self.name = name
        self.father = None
        self.mother = None
bob = Parent("bob")
mary = Parent("mary")
tom = Child("tom")
jerry = Child("jerry")
children = [tom, jerry]
bob.children = children
mary.children = children
tom.father = bob
tom.mother = mary
jerry.father = bob
jerry.mother = mary

Банда и член банды

Банда состоит из многих членов банды, но член банды не является бандой. Здесь нет наследства.

class Gang():
    def __init__(self, stuff):
        self.stuff = stuff
        self.members = []
class GangMember():
    # stuff

Несколько заключительных слов

Я надеюсь, что эти примеры прояснят, когда нам следует использовать наследование, а когда нет — нам часто нужно проверять, существует ли связь является между нашим предполагаемым дочерним классом и родительским классом. Если связь is-a не имеет смысла:

  • Студент математический класс
  • Ребенок – это родитель
  • Член банды - это банда

Давайте воздержимся от наследства.

Заключение

Если эта статья была полезной и вы хотите поддержать меня как автора, подумайте о том, чтобы подписаться на членство в Medium — это стоит 5 долларов в месяц, и вы получаете неограниченный доступ к историям на Medium. Если вы зарегистрируетесь по моей ссылке ниже, я получу небольшую комиссию без каких-либо дополнительных затрат для вас.

Зарегистрируйтесь, используя мою ссылку здесь, чтобы читать неограниченное количество статей на Medium!

Если эта статья была для вас очень ценной, подумайте о том, чтобы угостить меня кофе — каждый маленький вклад будет очень ценен!

https://www.buymeacoffee.com/zlliu

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



Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Получите эксклюзивный доступ к возможностям написания и советам в нашем сообществе Discord.