Узнайте, когда класс должен наследовать от другого класса.
Я встречал довольно много студентов, которые только начинали изучать объектно-ориентированное программирование (ООП) и были в замешательстве, когда класс должен наследоваться от другого класса. Таким образом, эта статья призвана сделать это как можно более ясным.
Когда использовать наследование (отношение 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. Если вы зарегистрируетесь по моей ссылке ниже, я получу небольшую комиссию без каких-либо дополнительных затрат для вас.
Если эта статья была для вас очень ценной, подумайте о том, чтобы угостить меня кофе — каждый маленький вклад будет очень ценен!
https://www.buymeacoffee.com/zlliu
Если вы хотите получать уведомления о моих публикациях, присоединитесь к моему списку рассылки.
Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Получите эксклюзивный доступ к возможностям написания и советам в нашем сообществе Discord.