[光-Hikari-のPython]09章-04クラス（メソッドのオーバーライド）

###[【目次リンク】へ戻る](https://qiita.com/ko0821/items/379e8bd9e6ea01089419)
#[Python]09章-04 メソッドのオーバーライド
前節では継承について触れました。継承を行うことで、差分のみのデータ（属性）やメソッド部分を書くだけで済むといったことも説明しました。

今回も引き続き継承についてもう少し深く触れていきたいと思います。

今回もBirdのスーパークラスを継承して、また別の種類の鳥のサブクラスを作成することを考えてみます。
例えば、**ペンギン（Penguin）**のサブクラスを作成することを考えてみましょう。
<font color=red>※</font>ペンギンは調べたところ、ラッパのような鳴き方をするようですが、具体的には不明です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/20908c6a-794b-825a-d29d-6e3970c25a3d.png)


前節の復習と思って、上記のクラス図を参考にプログラムを作成して実行してみましょう。<font color="#00cccc">chap09</font>の中に<font color="#00cccc">samp09_04_01.py</font>に以下のコードを書いてください。そして実行してみてください。
（ペンギンの名前や色は自由に指定してかまいません。）

```.samp09_04_01.py
#スーパークラスの記載
class Bird:
    def __init__(self, name, color):
        print('-----インスタンス化したと同時にコンストラクタを呼び出します。-----')
        self.name = name
        self.color = color

    #飛ぶというメソッド
    def fly(self, m):
        print('-----flyメソッドを呼び出します。-----')
        print(f'バサバサと{self.name}は空を飛びます。')
        print(f'{m}mの高さを飛んでいます。')

    #インスタンス化したBirdのステータスを出力するメソッド
    def print_status(self):
        print('-----print_statusメソッドを呼び出します。-----')
        print(f'{self.color}色の鳥です。')



#サブクラスの記載
class Penguin(Bird):
    def cry(self):
        print('-----ペンギン・サブクラスにあるcryメソッドを呼び出します。-----')
        print('ラッパを吹くような鳴き方です。')

#サブクラスのPenguinをインスタンス化する
pgn = Penguin('ペン太', '白と黒')

#ペンギン・サブクラスにあるcryメソッドを呼び出す
pgn.cry()

#スーパークラスにあるflyメソッドを呼び出す
pgn.fly(0)

#スーパークラスにあるprint_statusメソッドを呼び出す
pgn.print_status()
```
><font color="#090" bgcolor="black">【実行結果】</font>
-----インスタンス化したと同時にコンストラクタを呼び出します。-----
-----ペンギン・サブクラスにあるcryメソッドを呼び出します。-----
ラッパを吹くような鳴き方です。
**-----flyメソッドを呼び出します。-----**
**バサバサとペン太は空を飛びます。**
**0mの高さを飛んでいます。**
-----print_statusメソッドを呼び出します。-----
白と黒色の鳥です。

さて、実行結果を見て気づいた方もいるかと思いますが、ペンギンは空を飛びません。（同様にニワトリもそうです🐧🐔）
このままでは飛ばない鳥も**fly**メソッドで呼び出せてしまい、飛ぶことになってしまいます。

こういったケースの場合、どうすればよいのでしょうか？

##オーバーライド
先ほどのクラス図では、「鳥が空を飛ぶ」という前提でスーパークラスを作っていました。
しかし、先ほどのペンギンの例のように、空を飛ばない鳥の場合、クラスとメソッドが成り立ちません。

そこで、メソッドの**オーバーライド（上乗せ）**を使用します。
サブクラスには、スーパークラスにあるメソッド名と同じメソッド名を指定して、オーバーライドを行います。クラス図でイメージすると以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/bfd0034b-8573-c2ed-a3d5-340315221893.png)

クラス図を見てもわかる通り、**PenguinクラスはBirdクラスを継承**していますが、スーパークラスにある**fly()メソッド（「飛ぶ」と出力）**はサブクラスにある**fly()メソッド（「飛ばない」と出力）**を上乗せしています。

これをもとに、プログラムを作成してみましょう。<font color="#00cccc">chap09</font>の中に<font color="#00cccc">samp09_04_02.py</font>に以下のコードを書いてください。

```.samp09_04_02.py
#スーパークラスの記載
class Bird:
    def __init__(self, name, color):
        print('-----インスタンス化したと同時にコンストラクタを呼び出します。-----')
        self.name = name
        self.color = color

    #飛ぶというメソッド
    def fly(self, m):
        print('-----flyメソッドを呼び出します。-----')
        print(f'バサバサと{self.name}は空を飛びます。')
        print(f'{m}mの高さを飛んでいます。')

    #インスタンス化したBirdのステータスを出力するメソッド
    def print_status(self):
        print('-----print_statusメソッドを呼び出します。-----')
        print(f'{self.color}色の鳥です。')



#サブクラスの記載
class Penguin(Bird):
    def cry(self):
        print('-----ペンギン・サブクラスにあるcryメソッドを呼び出します。-----')
        print('ラッパを吹くような鳴き方です。')

    #メソッドのオーバーライドをしています
    def fly(self):
        print('-----ペンギン・サブクラスにあるflyメソッドを呼び出します。-----')
        print('ペンギンは空を飛びません。')
        print('地上を歩いています。')



#サブクラスのPenguinをインスタンス化する
pgn = Penguin('ペン太', '白と黒')

#ペンギン・サブクラスにあるflyメソッドを呼び出す
pgn.fly()

#ペンギン・サブクラスにあるcryメソッドを呼び出す
pgn.cry()

#スーパークラスにあるprint_statusメソッドを呼び出す
pgn.print_status()
```
><font color="#090" bgcolor="black">【実行結果】</font>
-----インスタンス化したと同時にコンストラクタを呼び出します。-----
-----ペンギン・サブクラスにあるflyメソッドを呼び出します。-----
ペンギンは空を飛びません。
地上を歩いています。
-----ペンギン・サブクラスにあるcryメソッドを呼び出します。-----
ラッパを吹くような鳴き方です。
-----print_statusメソッドを呼び出します。-----
白と黒色の鳥です。

今回注目してほしいのは、**pgn.fly()**の個所です。fly()メソッドは、サブクラスでオーバーライドをしているため、スーパークラスにもサブクラスにもfly()メソッドは存在していますが、どちらが呼び出されるかというと、**サブクラスにあるfly()メソッドが呼び出されています。**

メソッドのオーバーライドにより、メソッドが上乗せされていることが分かったかと思います。

実は、スーパークラスのfly()メソッドも呼び出すことができますが、こちらについては別の機会にお伝えします。

##最後に
今回はオーバーライドについて触れましたが、今後様々なライブラリを扱っていくうえではよく出てくる概念です。
基本情報技術者試験などでも出題される可能性があるかもしれませんので、プログラムを読めるようにしておきましょう。

###[【目次リンク】へ戻る](https://qiita.com/ko0821/items/379e8bd9e6ea01089419)