Java — перша мова, яку я вивчив у своїй кар’єрі. Його структура є основоположною в моїх перших роках розуміння концепцій програмування. Після вивчення кількох інших мов із дуже різними підходами я розширив свою точку зору. Сьогодні я хочу поміркувати про ідею спадщини .
У Java ідея успадкування тісно пов’язана з концепцією підтипу . Підтипування – це реалізація зв’язку IS A. Наприклад, клас Rabbit
є підтипом класу Mammal
. Відтепер екземпляр Rabbit
має всю поведінку Mammal
: він успадковує поведінку.
Через це ви можете передати екземпляр Rabbit
, коли метод викликає параметр Mammal
, або повернути екземпляр Rabbit
, коли тип повернення методу Mammal
. Якщо ви вивчили Java, .Net або щось подібне, ви бачите успадкування таким чином, і воно стає новою нормою.
Це явне успадкування .
class Animal { void feed(); } class Rabbit extends Animal { //1 }
Rabbit
IS A
Animal
, його можна feed()
Коли я вперше подивився на Go, я був вражений тим, що він не має підтипів, але все ще забезпечує успадкування. Go використовує качиний тип:
Якщо він виглядає як качка, плаває як качка і крякає як качка, то, ймовірно, це так.
Якщо struct
Go реалізує ті самі функції, що і інтерфейс, вона неявно реалізує інтерфейс.
type Animal interface { feed() //1 } type Rabbit struct { } func (rabbit Rabbit) feed() { //2 // feeds }
Animal
може годуватиfeed()
, яка приймає Rabbit
як параметр, Rabbit
реалізує Animal
Мені не подобається Go за його підхід до обробки помилок, але я не став проти неявної реалізації. З одного боку, я розумів, що це нова концепція, і намагався залишатися відкритим; з іншого боку, я думаю, що все завжди краще явно, ніж приховано, чи то в розробці програмного забезпечення, чи в реальному житті.
Python — найцікавіша мова, яку я знаю, щодо успадкування.
Підтипування та успадкування на основі типів присутні в Python з моменту його створення.
class Animal: def feed(self): #1 pass #2 class Rabbit(Animal): #3 pass
Animal
може годуватиRabbit
IS A
Animal
, його можна feed()
У цьому відношенні Python працює так само, як Java з точки зору успадкування. Python також пропонує качиний тип, який я описав як магічні методи . Наприклад, щоб зробити щось ітераційне , наприклад , що може повертати ітератор , вам потрібно лише реалізувати __iter__()
і __next__()
:
class SingleValueIterable(): done = False def __init__(self, value): self.value = value def __iter__(self): #1 return self def __next__(self): #1 if self.done: raise StopIteration else: self.done = True return self.value svi = SingleValueIterable(5) sviter = iter(svi) #2 for x in sviter: print(x) #3
Iterator
- Pythons знає як, оскільки ми реалізували методи вище5
Проблема з цим підходом качиного друку полягає в тому, що він працює лише для попередньо визначених магічних методів Python. Що, якщо ви хочете запропонувати клас, який третя сторона могла б неявно успадкувати?
class Animal: def feed(): pass class Rabbit: def feed(): pass
У наведеному вище фрагменті Rabbit
не є Animal
, на наш превеликий жаль. Введіть PEP 544 під назвою «Протоколи: структурне підтипування» (статичне типування). PEP вирішує неможливість визначення магічних методів для наших класів. Він визначає простий клас Protocol
: як тільки ви успадкуєте його, методи, визначені в класі, стають придатними для качиного введення, звідси і назва - статичний качиний тип.
from typing import Protocol class Animal(Protocol): #1 def feed(): #2 pass class Rabbit: def feed(): #2 pass class VenusFlytrap: def feed(): #2 pass
Protocol
Animal
є Protocol
, будь-який клас, який визначає feed()
стає Animal
, на краще чи гіршеОб’єктно-орієнтоване програмування, успадкування та підтипування можуть мати певні значення, які не перекладаються іншими мовами, залежно від першої мови, яку ви вивчаєте. Java рекламує себе як об'єктно-орієнтовану мову і пропонує повний пакет. Go не є мовою OO, але вона все ще пропонує підтипи за допомогою качиного введення. Python пропонує як явне, так і неявне успадкування, але без інтерфейсів.
Ви вивчаєте нову мову програмування, порівнюючи її з тими, які ви вже знаєте. Знання особливостей мови є ключовим для написання ідіоматичного коду цільовою мовою. Ознайомтеся з функціями, яких немає у ваших відомих мовах: вони розширять ваше розуміння програмування в цілому.
Йди далі:
Вперше опубліковано на сайті A Java Geek 26 січня 2025 року