Python3の復習(オブジェクトとクラス②-継承-)
こんにちは。
かにたまごです。
今日は復習メインでいこうと思っているので、記事多めです。たぶん。
今回は
- オブジェクトとクラス(継承)
について、復習していきたいと思います。
今までのPython3 復習履歴は以下の通り。
- 数値・文字列
- リスト・タプル
- 辞書・集合
- if文・while文・for文
- 内包表記
- 関数
- ジェネレータ
- デコレータ
- 名前空間とスコープ
- アンダーバー・アンダースコアの意味
- エラー処理:try・except
- モジュール・パッケージ
- 標準ライブラリ
- オブジェクトとクラス①-クラスの定義-
オブジェクトとクラス②-継承-
継承は、既存のクラスを受け継ぎつつ、新しいコードを追加することができる機能。
既存クラスのコピペ+新規コードでも実現することは可能だが、それは同じコードが二つ存在していることになるので無駄。それに、メンテナンス作業が面倒になる。
新しく定義するクラスでは、追加・変更したい部分だけ定義すればよい。
継承元のクラス定義を上書きすることをオーバーライドと呼ぶ。
そして、この継承元のクラスを親、スーパークラス、基底クラスと呼び、継承先のクラスを子、サブクラス、派生クラスと呼ぶ。
呼び方色々ありすぎぃ( ^ω^)・・・
適切ではないであろう例を用いて書いてみる。
class Anime(): def __init__(self, airtime): self.airtime = airtime def introduce(self): print("放送時間: {}分".format(self.airtime)) class Nitijo(Anime): pass nitijo = Nitijo(30) nitijo.introduce()
放送時間: 30分
継承先のクラスでメソッドを上書き(オーバーライド)してみる。
class Anime(): def __init__(self, airtime): self.airtime = airtime def introduce(self): print("放送時間: {}分".format(self.airtime)) class Nitijo(Anime): def introduce(self): print("ジャンル: 日常\n放送時間: {}分".format(self.airtime)) nitijo = Nitijo(30) nitijo.introduce()
ジャンル: 日常 放送時間: 30分
継承先にメソッドを追加して、個性を出す。
class Anime(): def __init__(self, airtime): self.airtime = airtime def introduce(self): print("放送時間: {}分".format(self.airtime)) class Nitijo(Anime): def introduce(self): print("ジャンル: 日常\n放送時間: {}分".format(self.airtime)) def honobono(self): print("ほのぼの系の日常アニメ") class Battle(Anime): def introduce(self): print("ジャンル: バトル\n放送時間: {}分".format(self.airtime)) def guro(self): print("グロ系のバトルアニメ") nitijo = Nitijo(30) nitijo.introduce() nitijo.honobono() battle = Battle(15) battle.introduce() battle.guro()
ジャンル: 日常 放送時間: 30分 ほのぼの系の日常アニメ ジャンル: バトル 放送時間: 15分 グロ系のバトルアニメ
ここで、継承元のAnimeインスタンスでNitijoクラスやBattleクラスで定義されたメソッドにアクセスしようとすると、エラーが発生する。
anime = Anime(30)
anime.introduce()
anime.honobono()
放送時間: 30分 Traceback (most recent call last): File "blog_test.py", line 922, in <module> anime.honobono() AttributeError: 'Anime' object has no attribute 'honobono'
- 継承元のメソッドを呼び出すsuper()
継承元から継承先にメソッドを引き継ぐ場合、明示的に継承元のメソッドを呼び出したほうがよい。
理由は主に二つある。
①例えば、__init__を継承先のクラスで新しく定義してしまうと、継承元の__init__はオーバーライドされてしまうため
②継承元のメソッドや属性に変更が合った場合に、継承先へ反映させるのが容易なため
以下のようにすると、継承元のメソッドを崩さずしてメソッドを引き継ぐことができる。
class Anime(): def __init__(self, airtime): self.airtime = airtime def introduce(self): print("放送時間: {}分".format(self.airtime)) class Nitijo(Anime): def __init__(self, airtime, honobonodo): super().__init__(airtime) self.honobonodo = honobonodo def introduce(self): print("ジャンル: 日常\n放送時間: {}分".format(self.airtime)) def honobono(self): print("ほのぼの系の日常アニメ\nほのぼの度: {}".format(self.honobonodo)) class Battle(Anime): def __init__(self, airtime, gurodo): super().__init__(airtime) self.gurodo = gurodo def introduce(self): print("ジャンル: バトル\n放送時間: {}分".format(self.airtime)) def guro(self): print("グロ系のバトルアニメ\nグロ度: {}".format(self.gurodo)) nitijo = Nitijo(30, 5) nitijo.introduce() nitijo.honobono() battle = Battle(15, 10) battle.introduce() battle.guro()
ジャンル: 日常 放送時間: 30分 ほのぼの系の日常アニメ ほのぼの度: 5 ジャンル: バトル 放送時間: 15分 グロ系のバトルアニメ グロ度: 10
継承元の__init__に属性が追加されても以下のように変更すれば、反映されたことが分かりやすくなる。
class Anime(): def __init__(self, airtime, company): self.airtime = airtime self.company = company def introduce(self): print("制作会社: {}\n放送時間: {}分".format(self.company, self.airtime)) class Nitijo(Anime): def __init__(self, airtime, company, honobonodo): super().__init__(airtime, company) self.honobonodo = honobonodo def introduce(self): print("制作会社: {}\nジャンル: 日常\n放送時間: {}分".format(self.company, self.airtime)) def honobono(self): print("ほのぼの系の日常アニメ\nほのぼの度: {}".format(self.honobonodo)) class Battle(Anime): def __init__(self, airtime, company, gurodo): super().__init__(airtime, company) self.gurodo = gurodo def introduce(self): print("制作会社: {}\nジャンル: バトル\n放送時間: {}分".format(self.company, self.airtime)) def guro(self): print("グロ系のバトルアニメ\nグロ度: {}".format(self.gurodo)) nitijo = Nitijo(30, "京都アニメーション", 5) nitijo.introduce() nitijo.honobono() battle = Battle(15,"BONES", 10) battle.introduce() battle.guro()
制作会社: 京都アニメーション ジャンル: 日常 放送時間: 30分 ほのぼの系の日常アニメ ほのぼの度: 5 制作会社: BONES ジャンル: バトル 放送時間: 15分 グロ系のバトルアニメ グロ度: 10
普段使ってないから、どういう使い方をしたら良いのかわからないな・・・。
汎用的なクラスを継承して、用途に応じて具体的な処理を付け足していったりする感じ・・・?
うーん。難しい。
以上です。