前書き

オブジェクト指向プログラミングは、再利用可能なコードのパターンを作成して、開発プロジェクトの冗長性を削減します。 1つのサブクラスが別の基本クラスのコードを活用できる場合、オブジェクト指向プログラミングがリサイクル可能なコードを実現する1つの方法は継承です。

このチュートリアルでは、親クラスと子クラスの動作方法、メソッドと属性のオーバーライド方法、 `+ super()+`関数の使用方法、利用方法など、Pythonの継承の主要な側面について説明します多重継承。

継承とは

*継承*は、クラスが別のクラス内で構築されたコードを使用する場合です。 生物学の観点から継承を考えると、子供が親から特定の特性を継承していると考えることができます。 つまり、子供は親の身長または目の色を継承できます。 また、子供は両親と同じ姓を共有する場合があります。

*子クラス*または*サブクラス*と呼ばれるクラスは、*親クラス*または*ベースクラス*からメソッドと変数を継承します。

class variables 子クラス + Child +`が `+ Parent +`から継承する `+ last_name ++ height +、および `+ eye_color +`の場合。

`+ Child `サブクラスは ` Parent `基本クラスから継承しているため、 ` Child `クラスは ` Parent +`のコードを再利用できるため、プログラマはコードの行数を減らして冗長性を減らすことができます。

親クラス

親クラスまたは基本クラスは、子クラスまたはサブクラスのベースとなるパターンを作成します。 親クラスを使用すると、毎回同じコードを書き直すことなく、継承を通じて子クラスを作成できます。 どのクラスも親クラスにすることができるため、それらはそれぞれ単なるテンプレートではなく、それ自体が完全に機能するクラスです。

「+ Personal_account 」と「 Business_account 」の子クラスを持つ一般的な「 Bank_account 」親クラスがあるとします。 お金を引き出したり預けたりする方法など、個人アカウントとビジネスアカウントの間のメソッドの多くは類似しているため、これらは親クラス「 Bank_account 」に属することができます。 ` Business_account `サブクラスには、おそらくビジネスレコードとフォームを収集する方法や、 ` employee_identification_number +`変数を含む、それに固有のメソッドがあります。

同様に、 `+ Animal `クラスには ` eating()`および ` sleeping()`メソッドがあり、 ` Snake `サブクラスには固有の ` hissing()`および ` slitheringが含まれる場合があります()+ `メソッド。

サブクラスとして魚のタイプを構築するために後で使用する「+ Fish +」親クラスを作成しましょう。 これらの魚にはそれぞれ、特性に加えて名と姓があります。

+ fish.py +`という新しいファイルを作成し、https://www.digitalocean.com/community/tutorials/how-to-construct-classes-and-define-objects-in-python-で開始します3#the-constructor-method [+ init ()` constructor method]。各 ` Fish `オブジェクトまたはサブクラスの ` first_name `および ` last_name +`クラス変数を設定します。

fish.py

class Fish:
   def __init__(self, first_name, last_name="Fish"):
       self.first_name = first_name
       self.last_name = last_name

ほとんどの魚が姓としてこれを持っていることがわかっているため、 `+ last_name `変数を文字列 `” Fish “+`で初期化しました。

他にもいくつかのメソッドを追加しましょう。

fish.py

class Fish:
   def __init__(self, first_name, last_name="Fish"):
       self.first_name = first_name
       self.last_name = last_name

すべてのサブクラスでもこれらのメソッドを利用できるように、メソッド+ `swim()`と ` swim backwards()`を ` Fish`クラスに追加しました。

作成する魚のほとんどは、https:// enではなくhttps://en.wikipedia.org/wiki/Osteichthyes[bony fish](骨から作られたスケルトンを持っているように)であると見なされるため、 .wikipedia.org / wiki / Chondrichthyes [軟骨魚](軟骨で作られたスケルトンがあるように)、 `+ init ()+`メソッドにいくつかの属性を追加できます:

fish.py

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.")

親クラスを作成する方法は、他のクラスを作成する方法と同じです。ただし、子クラスで作成したメソッドを子クラスで使用できるようにすることを考えています。

子クラス

子またはサブクラスは、親クラスから継承するクラスです。 これは、各子クラスが親クラスのメソッドと変数を利用できることを意味します。

たとえば、 `+ Fish `クラスをサブクラス化する ` Goldfish `子クラスは、宣言する必要なく、 ` Fish `で宣言された ` swim()+`メソッドを利用できます。

各子クラスは親クラスのクラスと考えることができます。 つまり、「+ Rhombus 」という子クラスと「 Parallelogram 」という親クラスがある場合、「 Rhombus 」は「 Goldfish 」と同様に「 Parallelogram 」であると言えます。 a * ` Fish +`です。

子クラスの最初の行は、親クラスを子クラスにパラメーターとして渡す必要があるため、非子クラスとは少し異なります。

class Trout(Fish):

+ Trout`クラスは + Fish`クラスの子です。 これは、括弧に「+ Fish +」という単語が含まれているためです。

子クラスでは、さらにメソッドを追加するか、既存の親メソッドをオーバーライドするか、 `+ pass +`キーワードを使用してデフォルトの親メソッドを受け入れるかを選択できます。この場合は次のようにします。

fish.py

...
class Trout(Fish):
   pass

追加のメソッドを定義することなく、 `+ Trout +`オブジェクトを作成できるようになりました。

fish.py

...
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 `子クラスでこれらのメソッドを定義していなくても、 ` Fish `クラスの各メソッドを使用する ` Trout `オブジェクト ` terry `を作成しました。 他の変数はすべて初期化されているため、 `” Terry “`の値を ` first_name +`変数に渡すだけで済みました。

プログラムを実行すると、次の出力が表示されます。

OutputTerry Fish
bone
False
The fish is swimming.
The fish can swim backwards.

次に、独自のメソッドを含む別の子クラスを作成しましょう。 このクラスを「+ Clownfish +」と呼び、その特別なメソッドによりイソギンチャクと一緒に暮らすことができます。

fish.py

...
class Clownfish(Fish):

   def live_with_anemone(self):
       print("The clownfish is coexisting with sea anemone.")

次に、 `+ Clownfish +`オブジェクトを作成して、この仕組みを確認します。

fish.py

...
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を使用できることを示しています。 ()+ `。

`+ Trout `オブジェクトで ` live_with_anemone()+`メソッドを使用しようとすると、エラーが表示されます。

Outputterry.live_with_anemone()
AttributeError: 'Trout' object has no attribute 'live_with_anemone'

これは、メソッド `+ live_with_anemone()`が ` Fish `親クラスではなく、 ` Clownfish +`子クラスにのみ属するためです。

子クラスは、それが属する親クラスのメソッドを継承するため、各子クラスはプログラム内でこれらのメソッドを利用できます。

親メソッドのオーバーライド

これまで、「+ pass 」キーワードを使用してすべての親クラスの「 Fish 」ビヘイビアを継承する子クラス「 Trout 」と、すべてを継承する別の子クラス「 Clownfish +」を見てきました親クラスの動作、および子クラスに固有の独自のメソッドも作成しました。 ただし、場合によっては、すべてではなく親クラスの動作の一部を使用することがあります。 親クラスのメソッドを変更すると、それらを*オーバーライド*します。

親クラスと子クラスを構築するときは、オーバーライドによって不要なコードや冗長なコードが生成されないように、プログラムの設計に留意することが重要です。

`+ Fish `親クラスの ` Shark `子クラスを作成します。 主に骨の多い魚を作成するという考えで ` Fish `クラスを作成したため、代わりに軟骨魚である ` Shark +`クラスを調整する必要があります。 プログラム設計に関しては、複数の非骨魚がいる場合、これらの2種類の魚のそれぞれに個別のクラスを作成することをお勧めします。

サメは、骨の多い魚とは異なり、骨ではなく軟骨でできた骨格を持っています。 まぶたもあり、後方に泳ぐことができません。 ただし、サメは沈むことで後方に移動できます。

これを踏まえて、 `+ init ()`コンストラクターメソッドと ` swim_backwards()`メソッドをオーバーライドします。 サメは泳ぐことができる魚なので、 ` swim()+`メソッドを変更する必要はありません。 この子クラスを見てみましょう。

fish.py

...
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 +`親クラスの文字列とは異なる文字列を出力するようになりました。これは、サメが硬い魚のように後方に泳ぐことができないためです。

これで、 `+ Fish `親クラスの ` swim()`メソッドを引き続き使用する ` Shark +`子クラスのインスタンスを作成できます。

fish.py

...
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

+ Shark In`子クラスは、 + Fish + 親クラスの + init ()+ および + swim backwards()+ メソッドを正常にオーバーライドしますが、 + swim()+ `メソッドも継承します親クラス。

他のクラスよりもユニークな子クラスの数が限られている場合、親クラスのメソッドをオーバーライドすることが有用であることがわかります。

`+ super()+`関数

`+ super()+`関数を使用すると、クラスオブジェクトで上書きされた継承メソッドにアクセスできます。

`+ super()+`関数を使用するとき、それを利用するために親メソッドを子メソッドに呼び出しています。 たとえば、親メソッドの特定の機能を特定の機能でオーバーライドした後、元の親メソッドの残りを呼び出してメソッドを終了したい場合があります。

学生を採点するプログラムでは、 `+ Grade `親クラスを継承する ` Weighted_grade `の子クラスが必要になる場合があります。 子クラスの ` Weighted_grade `では、加重グレードを計算する機能を含めるために親クラスの ` calculate_grade()`メソッドをオーバーライドできますが、それでも元のクラスの残りの機能は保持します。 ` super()+`関数を呼び出すことで、これを実現できます。

`+ super()`関数は、 ` init ()+`メソッド内で最も一般的に使用されます。これは、子クラスに一意性を追加し、親から初期化を完了する必要がある可能性が高いためです。

これがどのように機能するかを見るために、 + Trout +`子クラスを変更しましょう。 トラウトは一般的に淡水魚なので、 `+ water`変数を + init ()+ メソッドに追加し、文字列 + “freshwater” + `に設定しますが、残りの親クラスの変数は維持しますおよびパラメーター:

fish.py

...
class Trout(Fish):
   def __init__(self, water = "freshwater"):
       self.water = water
       super().__init__(self)
...

`+ Trout `子クラスの ` init ()`メソッドをオーバーライドし、親クラス ` Fish `で既に定義されている ` init ()`の異なる実装を提供しています。 ` Trout `クラスの ` init ()`メソッド内で、 ` Fish `クラスの ` init ()+`メソッドを明示的に呼び出しました。

メソッドをオーバーライドしたため、 `+ first_name `をパラメーターとして ` Trout `に渡す必要がなくなり、パラメーターを渡した場合は、代わりに ` freshwater `をリセットします。 したがって、オブジェクトインスタンスの変数を呼び出すことで、 ` first_name +`を初期化します。

これで、親クラスの初期化された変数を呼び出すことができ、一意の子変数も利用できます。 `+ Trout +`のインスタンスでこれを使用しましょう:

fish.py

...
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.

出力は、 + Trout +`子クラスのオブジェクト `+ terry +`が、子固有の `+ init ()+`変数 `+ water +`の両方を利用できる一方で、 `+ Fish + `親 + init ()+ 変数は、+ first_name ++ last_name +、および `+ eyelids +`の変数です。

組み込みのPython関数 `+ super()+`を使用すると、子クラスでこれらのメソッドの特定の側面をオーバーライドする場合でも、親クラスのメソッドを利用できます。

多重継承

*複数の継承*は、クラスが複数の親クラスから属性とメソッドを継承できる場合です。 これにより、プログラムは冗長性を減らすことができますが、ある程度の複雑さとあいまいさをもたらす可能性があるため、プログラム全体の設計を考慮して行う必要があります。

複数の継承がどのように機能するかを示すために、 `+ Coral `クラスと ` Sea_anemone `クラスから継承するよりも ` Coral_reef `子クラスを作成しましょう。 それぞれにメソッドを作成し、 ` Coral_reef `子クラスで ` pass +`キーワードを使用できます。

coral_reef.py

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

`+ Coral `クラスには、1行を印刷する ` community()`というメソッドがあり、 ` Anemone `クラスには、別の行を印刷する ` protect_clownfish()`というメソッドがあります。 次に、両方のクラスを継承https://www.digitalocean.com/community/tutorials/understanding-tuples-in-python-3[tuple]に呼び出します。 これは、「 Coral +」が2つの親クラスから継承していることを意味します。

`+ Coral +`オブジェクトをインスタンス化しましょう:

coral_reef.py

...
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(繰り返さないでください)の原則を順守することができ、より少ないコードと繰り返しでより多くのことが可能になります。 継承は、コードが効果的で明確であることを保証するために、作成しているプログラムをどのように設計しているかをプログラマーに考えさせます。