Java は、私がキャリアの中で最初に学んだ言語です。その構造は、プログラミングの概念を理解し始めた初期の頃の基礎となりました。まったく異なるアプローチを持つ他のいくつかの言語を経験したことで、私の視点は広がりました。今日は、 の考え方について考えてみたいと思います。 継承 Java における継承 Java では、 の考え方は の概念と密接に結びついています。サブタイプ化は 関係の実装です。たとえば、 クラスは クラスのサブタイプです。したがって、 インスタンスは のすべての を持ちます。つまり、動作を継承します。 継承 サブタイプ化 IS A Rabbit Mammal Rabbit Mammal 動作 このため、メソッドが パラメータを呼び出すときに インスタンスを渡したり、メソッドの戻り値の型が ときに インスタンスを返したりできます。Java、.Net、またはそれに似たものを学習したことがあるなら、継承をこのように捉えており、それが新しい標準になります。 Mammal Rabbit Mammal Rabbit です。 明示的な継承 class Animal { void feed(); } class Rabbit extends Animal { //1 } ので、 Rabbit Animal IS A feed() Goにおける継承 初めて Go を見たとき、継承を提供しながらサブタイプがないことに驚きました。Go はダックタイピングを使用します。 もしそれがアヒルのように見え、アヒルのように泳ぎ、アヒルのように鳴くなら、それはおそらくアヒルでしょう。 Go インターフェースと同じ関数を実装する場合、 。 struct 暗黙的にインターフェースを実装します type Animal interface { feed() //1 } type Rabbit struct { } func (rabbit Rabbit) feed() { //2 // feeds } 餌を与えることができる Animal パラメータとして受け取る 関数が存在するため、 実装します。 Rabbit feed() Rabbit Animal 私は Go のエラー処理アプローチが嫌いですが、暗黙的な実装については二つの考えがありました。一方では、それが新しい概念であることを理解し、偏見を持たないように努めました。他方では、ソフトウェア開発でも実生活でも、物事は常に暗黙的よりも明示的である方が良いと考えています。 Python における継承 Python は、継承に関して私が知る限り最も興味深い言語です。 サブタイプと型ベースの継承は、Python の誕生当初から存在しています。 class Animal: def feed(self): #1 pass #2 class Rabbit(Animal): #3 pass 餌を与えることができる Animal Pythonには抽象クラスもインターフェースもなく、クラスのみである。 ので、 Rabbit Animal IS A 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 ダックタイピング法 を作成する - Pythonは上記のメソッドを実装しているので、その方法を知っています Iterator 印刷 5 このダックタイピングのアプローチの問題は、Python の定義済みマジックメソッドに対してのみ機能することです。サードパーティが暗黙的に継承できるクラスを提供したい場合はどうすればよいでしょうか。 class Animal: def feed(): pass class Rabbit: def feed(): pass 上記のスニペットでは、残念なことに はありません。そこで、Protocols: Structural subtyping (static duck Typing) というタイトルの が登場します。この PEP は、クラスにマジック メソッドを定義することの不可能性を解決します。この PEP は、単純な クラスを定義します。このクラスを継承すると、クラスで定義されたメソッドはダック タイピングの対象となり、これが static duck Typing という名前につながっています。 Rabbit Animal PEP 544 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 は明示的継承と暗黙的継承の両方を提供していますが、インターフェースは提供していません。 新しいプログラミング言語を学ぶには、すでに知っている言語と比較します。言語の機能を知ることは、ターゲット言語で慣用的なコードを書くための鍵となります。知っている言語にはない機能に慣れておくと、プログラミング全体に対する理解が広がります。 さらに詳しく: 継承(オブジェクト指向プログラミング) ダックタイピング Python プロトコル 2025年1月26日に で最初に公開されました A Java Geek