Python

【Python】15.クラスの継承(1)継承、上乗り、呼び出し

クラスの継承

クラスは他のクラスに使い回す事ができます。これを継承(Inheritance)と呼び、クラスのメソッドを再利用したり、後から追加する事ができます。
継承の仕方は非常に簡単で、
class 新クラス名(継承したい旧クラス名):
これだけで継承できます。
さて、先程は加増をもらいそこねたので、今度は加増されるコードを書いてみます。

class Kokudaka:
    def __init__(self, kome):
        self.kome = kome

    def ryouchi(self):
        print("吉次は" + self.kome + "の領地をもらった。")

class Housyou(Kokudaka):
    def kazou (self):
        print("報奨として加増を受けた。")

koku = Kokudaka("300石")
koku.ryouchi()

Housyou = Housyou("100石")
Housyou.kazou()
Housyou.ryouchi()

石高というクラスを定義します。
コンストラクタで引数を自分・コメとします。
メソッド領地を定義します。
内容はコメ分の領地をもらったとします。

石高を継承するクラス報奨を作ります。
メソッドは加増なので報奨を受けたとします。
インスタンスkokuを作成。引数として300石とします。
その時の石高を出力します。
インスタンス報奨を作成。引数を100石とします。
報奨に対し加増を実行
報奨に対し領地を実行します。
メソッドはそれぞれ出力なので出力結果が表示されます。

出力結果
吉次は300石の領地をもらった。
報奨として加増を受けた。
吉次は100石の領地をもらった。

無事100石加増されましたね。
これでクラスの継承ができました!

classを継承すると、いろんな事ができるようになります。

上乗り(オーバーライド)

先に作られたclassを親クラス、親クラスを継承して新しく作成したクラスが子クラスとします。子クラスは親クラスと同じ名前のメソッドを子クラスで新たに定義して書き換える事ができます。
まずは羽柴軍の軍師を出力してみます。


class Hashiba:
	def __init__(self):
		self.yakume = "軍師"
		self.namae = "竹中半兵衛"

	def gunshi(self):
		print(self.yakume + " " + self.namae)

gundan = Hashiba()
gundan.gunshi()

1.class Hashibaを作成します
2.コンストラクタ
3.メソッドに役目という文字列を設定します
4.同じく名前を竹中半兵衛とします。
5.新しいメソッド「軍師」を設定します。
6.役目と名前を出力します。
7.インスタンス「軍団」を「羽柴」から作ります。
8.インスタンス軍団は命令「軍師」を行います。

出力結果
竹中半兵衛

では、class羽柴を継承するclass豊臣を作ります。ところが竹中半兵衛は病没してしましますので、豊臣軍の軍師は入れ替えねばなりません。


class Hashiba:
	def __init__(self):
		self.yakume = "軍師"
		self.namae = "竹中半兵衛"

	def gunshi(self):
		print(self.yakume + " " + self.namae)
class Toyotomi(Hashiba):
	def gunshi(self , namae):
		 print(self.yakume + " " + namae)

gundan = Toyotomi()
gundan.gunshi("黒田官兵衛")


9.class豊臣を作成し、羽柴を継承します。
10.子classで「軍師」と同じメソッドを作って上乗りし、第2引数で「名前」を引き取るように変更します。
11.役目と名前を出力します。
12.class豊臣から軍団を作ります。
13.インスタンス軍団は命令軍師を行います。

出力結果
黒田官兵衛

羽柴から豊臣に継承し、軍師を竹中半兵衛から黒田官兵衛に変更して出力しました。このように子classは親classのメソッドを上乗り(オーバーライド)する事ができます。

ループでメソッドを繰り返し呼び出す

ほとんどの場合、関数は繰り返し使えるのが前提になります。繰り返しにも何種類かありますが、まずはループを使って関数を繰り返し呼び出してみましょう。関ヶ原の戦いで東軍武将が西軍に攻撃するコードを書いてみます。

class Busyou: def __init__(self , busyou): self.busyou = busyou
 def kougeki(self , mitsunari): print(self.busyou + "は、" + mitsunari + "を攻撃した!") print( mitsunari + "に2000の損害を与えた")
tougun_1 = Busyou("黒田長政")tougun_2 = Busyou("加藤清正")tougun_3 = Busyou("小早川金吾")
tougun = [tougun_1 , tougun_2 , tougun_3]for busyou in tougun: busyou.kougeki("西軍")

1.class「武将」を定義します。今更ですがclass名の最初は大文字です。
2.コンストラクタ。
3.与えられた値を武将として格納します。
4.変数も同じ名前ですが全て小文字にしました。
5.関数「攻撃」を定義します。引数はmitsunariとして取り込みます。
6.武将はmitsunariを攻撃したと出力する事にします。とりあえず定形で2000の損害を与えると出力する事にします。
7.class武将を元にtougun_1 ~3のインスタンスを作成します。
8.長政、清正、小早川金吾とします。武将たちを東軍リストに格納します。ちょっと面倒ですが今回はいちいち書き込みます。
9.for分開始 名前はまたbusyouとします。東軍リストがある限り繰り返します。
10.busyouの中身は関数kougekiを実行します。攻撃の引数は西軍とします。

出力結果
黒田長政は、西軍を攻撃した!
西軍に2000の損害を与えた加藤清正は、西軍を攻撃した!
西軍に2000の損害を与えた加藤清正は、西軍を攻撃した!
西軍に2000の損害を与えた

東軍リストにある武将たちが西軍を攻撃するコードが書けました!一人西軍のはずのヤツがいますね。

継承したclassでオーバーライドしてみる

先程のコードを少し進化させて、次に継承したclass内の関数にオーバーライドしてみます。ついでにリストも進化してappend関数で追加していきます。関ヶ原本戦でなく信州上田城の戦いを見てみましょう。

class Busyou:    def __init__(self, busyou):        self.busyou = busyou
    def kougeki(self, uedazyou):        print(self.busyou + "は" + uedazyou + "を攻撃した")
class Syougun(Busyou):    def kougeki(self, uedazyou):        print(self.busyou + "は" + uedazyou + "を包囲した")
tougun  = []tougun .append(Busyou("大久保忠隣"))tougun .append(Busyou("榊原康政"))tougun .append(Syougun("徳川秀忠"))
for hidetada in tougun :    hidetada .kougeki("上田城")

1.再びclass武将を使いますが、損害のprintを消します。
2.武将を継承したclass大名を定義します。
3.ここで攻撃をオーバーライドして、攻撃でなく攻囲してみます。
4.リスト東軍を定義します
5.東軍に対し、Busyouから作った大久保忠隣、榊原康政、Syougunから作った6.徳川秀忠をappend関数で代入します。
7.for文開始。名前はhidetada にして、リスト東軍がある限りループします。
8.ループ内でメソッド攻撃を呼び出します。引数は上田城にします。

出力結果
大久保忠隣は上田城を攻撃した
榊原康政は上田城を攻撃した
徳川秀忠は上田城を包囲した

まあ攻囲しても結局陥とせないんですけどね!