Python 3でクラスに多態性を適用する方法

前書き

Polymorphismは、data typesclassesなどのさまざまな基になるフォームに同じインターフェイスを活用する機能です。 これにより、functionsは異なるタイプのエンティティを異なる時間に使用できます。

Pythonのオブジェクト指向プログラミングの場合、これは、特定のクラスに属する特定のオブジェクトを、別のクラスに属する別のオブジェクトであるかのように使用できることを意味します。

多態性により、柔軟性と疎結合が可能になるため、コードを拡張し、長期にわたって容易に維持できます。

このチュートリアルでは、Pythonのクラスにポリモーフィズムを適用します。

多型とは

ポリモーフィズムはPythonのクラス定義の重要な機能であり、クラスまたはサブクラス全体で一般的に名前の付いたメソッドがある場合に利用されます。 これにより、クラス全体の違いを意識する必要なく、関数はこれらの多態性クラスのオブジェクトを使用できます。

ポリモーフィズムは、サブクラスが基本クラスのメソッドを使用するか、それらをオーバーライドして、inheritanceを介して実行できます。

動的型付けの特殊なケースであるPythonのduck typingは、late bindingdynamic dispatchなどのポリモーフィズムに特徴的な手法を使用します。 「アヒルのタイピング」という用語は、作家のジェームズ・ホイットコム・ライリーの引用に由来します。 comp.lang.pythonニュースグループへのメッセージの中でコンピューターエンジニアのAlex Martelliが、アヒルタイピングの使用は、特定の目的に対するオブジェクトの適合性の確立に関係しています。 通常のタイピングを使用する場合、この適合性はオブジェクトのタイプのみによって決定されますが、アヒルのタイピングでは、問題のオブジェクトの実際のタイプではなくメソッドとプロパティの存在が使用されます。 つまり、オブジェクトがアヒルであるかどうかを尋ねるのではなく、オブジェクトがアヒルのように鳴き、アヒルのように歩くかどうかを確認します。

複数のクラスまたはサブクラスが同じメソッド名を持っているが、これらの同じメソッドの実装が異なる場合、クラスは単一のインターフェースを使用して異なるタイプのエンティティで使用するため、ポリモーフィックです。 関数は、どのクラスが呼び出されるかを知らなくても、これらの多態性メソッドを評価できます。

ポリモーフィッククラスの作成

ポリモーフィズムを利用するために、2つの異なるオブジェクトで使用する2つの異なるクラスを作成します。 これらの異なるクラスにはそれぞれ、多相的に使用できるように共通のインターフェイスが必要です。そのため、同じ名前の異なるメソッドを提供します。

SharkクラスとClownfishクラスを作成します。それぞれが、swim()swim_backwards()、およびskeleton()のメソッドを定義します。

polymorphic_fish.py

class Shark():
    def swim(self):
        print("The shark is swimming.")

    def swim_backwards(self):
        print("The shark cannot swim backwards, but can sink backwards.")

    def skeleton(self):
        print("The shark's skeleton is made of cartilage.")


class Clownfish():
    def swim(self):
        print("The clownfish is swimming.")

    def swim_backwards(self):
        print("The clownfish can swim backwards.")

    def skeleton(self):
        print("The clownfish's skeleton is made of bone.")

上記のコードでは、SharkクラスとClownfishクラスの両方に、同じ名前の3つのメソッドが共通しています。 ただし、これらのメソッドの機能はクラスごとに異なります。

これらのクラスを2つのオブジェクトにインスタンス化します。

polymorphic_fish.py

...
sammy = Shark()
sammy.skeleton()

casey = Clownfish()
casey.skeleton()

python polymorphic_fish.pyコマンドを使用してプログラムを実行すると、各オブジェクトが期待どおりに動作することがわかります。

OutputThe shark's skeleton is made of cartilage.
The clownfish's skeleton is made of bone.

共通のインターフェースを使用する2つのオブジェクトができたので、個々のタイプに関係なく同じ方法で2つのオブジェクトを使用できます。

クラスメソッドを使用した多態性

Pythonがこれらの異なるクラスタイプのそれぞれを同じように使用する方法を示すために、最初に、オブジェクトのtupleを反復処理するfor loopを作成できます。 その後、各オブジェクトがどのクラス型であるかを気にせずにメソッドを呼び出すことができます。 これらのメソッドが各クラスに実際に存在することのみを想定します。

polymorphic_fish.py

...
sammy = Shark()

casey = Clownfish()

for fish in (sammy, casey):
    fish.swim()
    fish.swim_backwards()
    fish.skeleton()

SharkクラスのsammyClownfishクラスのcaseyの2つのオブジェクトがあります。 forループはこれらのオブジェクトを反復処理し、それぞれでswim()swim_backwards()、およびskeleton()メソッドを呼び出します。

プログラムを実行すると、出力は次のようになります。

OutputThe shark is swimming.
The shark cannot swim backwards, but can sink backwards.
The shark's skeleton is made of cartilage.
The clownfish is swimming.
The clownfish can swim backwards.
The clownfish's skeleton is made of bone.

forループは、最初にSharkクラスのsammyインスタンス化を繰り返し、次にClownfishクラスのcaseyオブジェクトを繰り返したので、に関連するメソッドが表示されます。最初にSharkクラス、次にClownfishクラス。

これは、Pythonがこれらの各オブジェクトがどのクラス型であるかを正確に知らない、または気にせずにこれらのメソッドを使用していることを示しています。 つまり、これらのメソッドを多態的に使用します。

関数を使用した多態性

また、任意のオブジェクトを受け取ることができる関数を作成して、ポリモーフィズムを可能にすることもできます。

fishを呼び出すことができるオブジェクトを取り込むin_the_pacific()という関数を作成しましょう。 fishという名前を使用していますが、インスタンス化されたオブジェクトはすべて、この関数で呼び出すことができます。

polymorphic_fish.py

…
def in_the_pacific(fish):

次に、渡されたfishオブジェクトを使用する関数を実行します。 この場合、swim()メソッドを呼び出します。各メソッドは、2つのクラスSharkClownfishで定義されています。

polymorphic_fish.py

...
def in_the_pacific(fish):
    fish.swim()

次に、SharkクラスとClownfishクラスの両方のインスタンス化をまだ作成していない場合は、作成します。 これらを使用すると、同じin_the_pacific()関数を使用してアクションを呼び出すことができます。

polymorphic_fish.py

...
def in_the_pacific(fish):
    fish.swim()

sammy = Shark()

casey = Clownfish()

in_the_pacific(sammy)
in_the_pacific(casey)

プログラムを実行すると、出力は次のようになります。

OutputThe shark is swimming.
The clownfish is swimming.

ランダムオブジェクト(fish)を定義時にin_the_pacific()関数に渡しましたが、それでもSharkクラスとClownfishクラスのインスタンス化に効果的に使用できました。 。 Clownfishクラスで定義されたswim()メソッドと呼ばれるcaseyオブジェクト、およびSharkクラスで定義されたswim()メソッドと呼ばれるsammyオブジェクト。

結論

さまざまなオブジェクトがポリモーフィズムを介して同様の方法で関数とメソッドを活用できるようにすることで、このPython機能を使用すると、オブジェクト指向コードの柔軟性と拡張性が向上します。