序章
オブジェクト指向プログラミングは、再利用可能なコードパターンを作成して、開発プロジェクトの冗長性を削減します。 オブジェクト指向プログラミングがリサイクル可能なコードを実現する1つの方法は、あるサブクラスが別の基本クラスのコードを活用できる場合の継承です。
このチュートリアルでは、親クラスと子クラスの動作、メソッドと属性のオーバーライド方法、Pythonでの継承の使用方法など、Pythonの継承の主要な側面について説明します。 super()
関数、および多重継承を利用する方法。
前提条件
Python 3をインストールし、コンピューターまたはサーバーにプログラミング環境をセットアップする必要があります。 プログラミング環境をセットアップしていない場合は、ローカルプログラミング環境またはサーバー上のプログラミング環境のインストールおよびセットアップガイドを参照して、オペレーティングに適したものにすることができます。システム(Ubuntu、CentOS、Debianなど)
継承とは何ですか?
継承は、クラスが別のクラス内で構築されたコードを使用する場合です。 生物学の観点から遺伝を考えると、子供が親から特定の特性を継承していると考えることができます。 つまり、子供は親の身長または目の色を継承できます。 子供は両親と同じ名前を共有することもできます。
子クラスまたはサブクラスと呼ばれるクラスは、親クラスまたは基本クラスからメソッドと変数を継承します。
と呼ばれる親クラスを考えることができます Parent
クラス変数があります last_name
, height
、 と eye_color
その子クラス Child
から継承します Parent
.
なぜなら Child
サブクラスはから継承しています Parent
基本クラス、 Child
クラスはのコードを再利用できます Parent
、プログラマーが使用するコード行を減らし、冗長性を減らすことができます。
親クラス
親クラスまたは基本クラスは、子またはサブクラスの基になるパターンを作成します。 親クラスを使用すると、毎回同じコードを書き直すことなく、継承を通じて子クラスを作成できます。 どのクラスも親クラスにすることができるので、それらは単なるテンプレートではなく、それ自体で完全に機能するクラスです。
将軍がいるとしましょう Bank_account
持っている親クラス Personal_account
と Business_account
子クラス。 個人口座とビジネス口座の間の方法の多くは、お金を引き出したり預けたりする方法など、類似しているため、それらはの親クラスに属することができます。 Bank_account
. The Business_account
サブクラスには、ビジネスレコードやフォームを収集する方法など、それに固有のメソッドがあります。 employee_identification_number
変数。
同様に、 Animal
クラスは持っているかもしれません eating()
と sleeping()
メソッド、および Snake
サブクラスには、独自のサブクラスが含まれる場合があります hissing()
と slithering()
メソッド。
を作成しましょう Fish
後でサブクラスとして魚のタイプを構築するために使用する親クラス。 これらの魚のそれぞれは、特徴に加えて、名と姓を持ちます。
情報:このチュートリアルのサンプルコードに従うには、ローカルシステムでPythonインタラクティブシェルを開いて、 python3
指図。 次に、例の後に追加して、例をコピー、貼り付け、または編集できます。 >>>
促す。
という新しいファイルを作成します fish.py
そして、 __ init __()コンストラクターメソッドから始めます。 first_name
と last_name
それぞれのクラス変数 Fish
オブジェクトまたはサブクラス。
class Fish:
def __init__(self, first_name, last_name="Fish"):
self.first_name = first_name
self.last_name = last_name
初期化済み last_name
文字列を持つ変数 "Fish"
ほとんどの魚の名前がこれになることがわかっているからです。
他のメソッドもいくつか追加しましょう。
class Fish:
def __init__(self, first_name, last_name="Fish"):
self.first_name = first_name
self.last_name = last_name
def swim(self):
print("The fish is swimming.")
def swim_backwards(self):
print("The fish can swim backwards.")
メソッドを追加しました swim()
と swim_backwards()
に Fish
クラス。これにより、すべてのサブクラスもこれらのメソッドを利用できるようになります。
作成する魚のほとんどは、軟骨魚ではなく硬骨魚(骨格が骨でできているため)と見なされるためです。軟骨で作られた骨格)、さらにいくつかの属性を追加することができます __init__()
方法:
class Fish:
def __init__(self, first_name, last_name="Fish",
skeleton="bone", eyelids=False):
self.first_name = first_name
self.last_name = last_name
self.skeleton = skeleton
self.eyelids = eyelids
def swim(self):
print("The fish is swimming.")
def swim_backwards(self):
print("The fish can swim backwards.")
親クラスの構築は、他のクラスの構築と同じ方法論に従いますが、子クラスを作成した後、子クラスがどのメソッドを使用できるかを検討している点が異なります。
子クラス
子またはサブクラスは、親クラスから継承するクラスです。 つまり、各子クラスは親クラスのメソッドと変数を利用できるようになります。
たとえば、 Goldfish
サブクラス化する子クラス Fish
クラスはを利用できるようになります swim()
で宣言されたメソッド Fish
宣言する必要はありません。
各子クラスは、親クラスのクラスであると考えることができます。 つまり、という子クラスがある場合 Rhombus
と呼ばれる親クラス Parallelogram
、私たちはそれを言うことができます Rhombus
はです Parallelogram
、ちょうど Goldfish
はです Fish
.
子クラスの最初の行は、親クラスをパラメーターとして子クラスに渡す必要があるため、非子クラスとは少し異なります。
class Trout(Fish):
The Trout
クラスはの子です Fish
クラス。 単語が含まれているので、これを知っています Fish
括弧内。
子クラスでは、メソッドを追加するか、既存の親メソッドをオーバーライドするか、デフォルトの親メソッドを受け入れるかを選択できます。 pass
この場合に実行するキーワード:
...
class Trout(Fish):
pass
これで、 Trout
追加のメソッドを定義する必要なしにオブジェクト。
...
class Trout(Fish):
pass
terry = Trout("Terry")
print(terry.first_name + " " + terry.last_name)
print(terry.skeleton)
print(terry.eyelids)
terry.swim()
terry.swim_backwards()
作成しました Trout
物体 terry
それはのそれぞれの方法を利用します Fish
これらのメソッドをで定義しなかったとしても、クラス Trout
子クラス。 の値を渡すだけで済みました "Terry"
に first_name
他のすべての変数が初期化されたため、変数。
プログラムを実行すると、次の出力が表示されます。
OutputTerry Fish
bone
False
The fish is swimming.
The fish can swim backwards.
次に、独自のメソッドを含む別の子クラスを作成しましょう。 このクラスを呼びます Clownfish
、そしてその特別な方法はそれがイソギンチャクと一緒に暮らすことを可能にします:
...
class Clownfish(Fish):
def live_with_anemone(self):
print("The clownfish is coexisting with sea anemone.")
次に、を作成しましょう Clownfish
これがどのように機能するかを確認するためのオブジェクト:
...
casey = Clownfish("Casey")
print(casey.first_name + " " + casey.last_name)
casey.swim()
casey.live_with_anemone()
プログラムを実行すると、次の出力が表示されます。
OutputCasey Fish
The fish is swimming.
The clownfish is coexisting with sea anemone.
出力は、 Clownfish
物体 casey
使用することができます Fish
メソッド __init__()
と swim()
の子クラスメソッドと同様に live_with_anemone()
.
使用しようとすると live_with_anemone()
のメソッド Trout
オブジェクト、エラーを受け取ります:
Outputterry.live_with_anemone()
AttributeError: 'Trout' object has no attribute 'live_with_anemone'
これは、メソッドが live_with_anemone()
にのみ属します Clownfish
子クラスであり、 Fish
親クラス。
子クラスは、それが属する親クラスのメソッドを継承するため、各子クラスはプログラム内でそれらのメソッドを利用できます。
親メソッドのオーバーライド
これまで、子クラスを見てきました Trout
それを利用した pass
すべての親クラスを継承するキーワード Fish
行動、および別の子クラス Clownfish
これは、すべての親クラスの動作を継承し、子クラスに固有の独自のメソッドも作成しました。 ただし、親クラスの動作のすべてではなく、一部を使用したい場合があります。 親クラスのメソッドを変更すると、それらをオーバーライドします。
親クラスと子クラスを作成するときは、オーバーライドによって不要なコードや冗長なコードが生成されないように、プログラムの設計を念頭に置くことが重要です。
作成します Shark
の子クラス Fish
親クラス。 作成したので Fish
私たちが主に硬骨魚を作るという考えを持ったクラスでは、調整を行う必要があります Shark
代わりに軟骨魚であるクラス。 プログラムの設計に関しては、硬骨魚以外の魚が複数いる場合は、これら2種類の魚ごとに別々のクラスを作成することをお勧めします。
サメは硬骨魚とは異なり、骨ではなく軟骨でできた骨格を持っています。 また、まぶたがあり、後ろ向きに泳ぐことはできません。 ただし、サメは沈むことで後方に移動することができます。
これに照らして、オーバーライドします __init__()
コンストラクターメソッドと swim_backwards()
方法。 変更する必要はありません swim()
サメは泳ぐことができる魚なので、方法。 この子クラスを確認しましょう:
...
class Shark(Fish):
def __init__(self, first_name, last_name="Shark",
skeleton="cartilage", eyelids=True):
self.first_name = first_name
self.last_name = last_name
self.skeleton = skeleton
self.eyelids = eyelids
def swim_backwards(self):
print("The shark cannot swim backwards, but can sink backwards.")
初期化されたパラメータをオーバーライドしました __init__()
メソッド、そのように last_name
変数が文字列と等しく設定されるようになりました "Shark"
、 skeleton
変数が文字列と等しく設定されるようになりました "cartilage"
、 そしてその eyelids
変数がブール値に設定されるようになりました True
. クラスの各インスタンスは、これらのパラメーターをオーバーライドすることもできます。
方法 swim_backwards()
内の文字列とは異なる文字列を出力するようになりました Fish
サメは硬骨魚のように後ろ向きに泳ぐことができないため、親クラスです。
これで、のインスタンスを作成できます Shark
子クラス、これはまだ利用します swim()
の方法 Fish
親クラス:
...
sammy = Shark("Sammy")
print(sammy.first_name + " " + sammy.last_name)
sammy.swim()
sammy.swim_backwards()
print(sammy.eyelids)
print(sammy.skeleton)
このコードを実行すると、次の出力が返されます。
OutputSammy Shark
The fish is swimming.
The shark cannot swim backwards, but can sink backwards.
True
cartilage
The Shark
子クラスは正常にオーバーライドしました __init__()
と swim_backwards()
の方法 Fish
親クラス、また継承している間 swim()
親クラスのメソッド。
他のクラスよりも一意な子クラスの数が限られている場合は、親クラスのメソッドをオーバーライドすると便利です。
The super()
関数
とともに super()
関数を使用すると、クラスオブジェクトで上書きされた継承されたメソッドにアクセスできます。
私たちが使用するとき super()
関数では、親メソッドを子メソッドに呼び出して使用します。 たとえば、親メソッドの1つの側面を特定の機能でオーバーライドした後、元の親メソッドの残りの部分を呼び出してメソッドを終了したい場合があります。
生徒を評価するプログラムでは、子供向けのクラスが必要になる場合があります Weighted_grade
から継承します Grade
親クラス。 子供のクラスで Weighted_grade
、オーバーライドしたい場合があります calculate_grade()
加重グレードを計算する機能を含めるための親クラスのメソッド。ただし、元のクラスの残りの機能は保持します。 を呼び出すことによって super()
機能これを達成することができます。
The super()
関数は、 __init__()
メソッドは、子クラスに一意性を追加してから、親からの初期化を完了する必要がある可能性が高いためです。
これがどのように機能するかを確認するために、 Trout
子クラス。 マスは通常淡水魚なので、追加しましょう water
に可変 __init__()
メソッドとそれを文字列と等しく設定します "freshwater"
、ただし、親クラスの残りの変数とパラメーターを維持します。
...
class Trout(Fish):
def __init__(self, water = "freshwater"):
self.water = water
super().__init__(self)
...
オーバーライドしました __init__()
のメソッド Trout
子クラス、の異なる実装を提供します __init__()
親クラスによってすでに定義されている Fish
. 以内 __init__()
私たちの方法 Trout
明示的に呼び出したクラス __init__()
の方法 Fish
クラス。
メソッドをオーバーライドしたため、パスする必要がなくなりました first_name
パラメータとしてで Trout
、パラメータを渡した場合、リセットされます freshwater
代わりは。 したがって、初期化します first_name
オブジェクトインスタンスで変数を呼び出すことによって。
これで、親クラスの初期化された変数を呼び出し、一意の子変数を利用することもできます。 これを次のインスタンスで使用してみましょう Trout
:
...
terry = Trout()
# Initialize first name
terry.first_name = "Terry"
# Use parent __init__() through super()
print(terry.first_name + " " + terry.last_name)
print(terry.eyelids)
# Use child __init__() override
print(terry.water)
# Use parent swim() method
terry.swim()
OutputTerry Fish
False
freshwater
The fish is swimming.
出力は、オブジェクトが terry
の Trout
子クラスは、子固有の両方を利用できます __init__()
変数 water
を呼び出すこともできます Fish
親 __init__()
の変数 first_name
, last_name
、 と eyelids
.
組み込みのPython関数 super()
子クラスでこれらのメソッドの特定の側面をオーバーライドする場合でも、親クラスのメソッドを利用できます。
多重継承
多重継承は、クラスが複数の親クラスから属性とメソッドを継承できる場合です。 これにより、プログラムの冗長性を減らすことができますが、ある程度の複雑さとあいまいさをもたらす可能性もあるため、プログラム全体の設計を考慮して行う必要があります。
多重継承がどのように機能するかを示すために、 Coral_reef
から継承するよりも子クラス Coral
クラスと Sea_anemone
クラス。 それぞれにメソッドを作成してから、 pass
のキーワード Coral_reef
子クラス:
class Coral:
def community(self):
print("Coral lives in a community.")
class Anemone:
def protect_clownfish(self):
print("The anemone is protecting the clownfish.")
class CoralReef(Coral, Anemone):
pass
The Coral
クラスにはというメソッドがあります community()
1行を印刷し、 Anemone
クラスにはというメソッドがあります protect_clownfish()
別の行を印刷します。 次に、両方のクラスを継承tupleに呼び出します。 この意味は CoralReef
2つの親クラスから継承しています。
今すぐインスタンス化しましょう CoralReef
物体:
...
great_barrier = CoralReef()
great_barrier.community()
great_barrier.protect_clownfish()
オブジェクト great_barrier
として設定されます CoralReef
オブジェクトであり、両方の親クラスのメソッドを使用できます。 プログラムを実行すると、次の出力が表示されます。
OutputCoral lives in a community.
The anemone is protecting the clownfish.
出力は、両方の親クラスのメソッドが子クラスで効果的に使用されたことを示しています。
多重継承により、子クラスの複数の親クラスからのコードを使用できます。 同じメソッドが複数の親メソッドで定義されている場合、子クラスはタプルリストで宣言された最初の親のメソッドを使用します。
効果的に使用できますが、プログラムが曖昧になったり、他のプログラマーが理解しにくくなったりしないように、多重継承は注意して行う必要があります。
結論
このチュートリアルでは、親クラスと子クラスを作成し、子クラス内の親メソッドと属性をオーバーライドして、 super()
関数、および子クラスが複数の親クラスから継承できるようにします。
オブジェクト指向コーディングの継承により、ソフトウェア開発のDRY(自分自身を繰り返さないでください)の原則を順守できるようになり、少ないコードと繰り返しでより多くのことを実行できるようになります。 また、継承により、プログラマーは、コードが効果的で明確であることを確認するために、作成しているプログラムをどのように設計しているかについて考える必要があります。