01 / 07
受けついだままでは合わないとき
親に書いた aisatsu は「こんにちは」と言う。でもプレミアム会員には「いつもありがとうございます」と言わせたい。
このために premium_aisatsu のような別の名前のメソッドを足すと、呼ぶ側が相手によって呼ぶ名前を変えることになってしまう。それは避けたいよね。
クラス
INPUT · スライド
01 / 07
親に書いた aisatsu は「こんにちは」と言う。でもプレミアム会員には「いつもありがとうございます」と言わせたい。
このために premium_aisatsu のような別の名前のメソッドを足すと、呼ぶ側が相手によって呼ぶ名前を変えることになってしまう。それは避けたいよね。
02 / 07
子クラスに親と同じ名前のメソッドを書くと、その子ではそっちが使われる。これをオーバーライド(上書き)と呼ぶよ。
呼ぶ側は今までどおり aisatsu() と書くだけ。動きだけが差し替わるんだ。
class Kaiin: def __init__(self, namae): self.namae = namae def aisatsu(self): print(f"{self.namae}さん、こんにちは")class PremiumKaiin(Kaiin): def aisatsu(self): print(f"{self.namae}さん、いつもありがとうございます")p = PremiumKaiin("ゆい")p.aisatsu()実行結果
ゆいさん、いつもありがとうございます
03 / 07
上書きされるのはその子から呼んだときだけ。親のメソッドは無事に残っているし、ほかの子にも影響しないよ。
Python はメソッドを呼ばれると、まず子を探して、無ければ親を見に行く。子に同じ名前があれば、親まで行かずにそこで見つかる——それだけのことなんだ。
class Kaiin: def __init__(self, namae): self.namae = namae def aisatsu(self): print(f"{self.namae}さん、こんにちは")class PremiumKaiin(Kaiin): def aisatsu(self): print(f"{self.namae}さん、いつもありがとうございます")k = Kaiin("はると")p = PremiumKaiin("ゆい")k.aisatsu()p.aisatsu()実行結果
はるとさん、こんにちは ゆいさん、いつもありがとうございます
04 / 07
上書きしたうえで、親のもとの処理も使いたいことがある。そんなときは super()(スーパー)と書くよ。
super().aisatsu() は「親のほうの aisatsu を走らせて」という意味。親のぶんをやってから、自分の分を足せるんだ。
class Kaiin: def __init__(self, namae): self.namae = namae def aisatsu(self): print(f"{self.namae}さん、こんにちは")class PremiumKaiin(Kaiin): def aisatsu(self): super().aisatsu() print("いつもありがとうございます")p = PremiumKaiin("ゆい")p.aisatsu()実行結果
ゆいさん、こんにちは いつもありがとうございます
05 / 07
プレミアム会員にだけ「ランク」を持たせたい。つまり __init__ を子で上書きしたい。
このとき super().__init__(namae) を先に呼ぶ。親がやることは親にまかせて、子は増えたぶんだけ書く。これが継承のいちばん定番の形だよ。
class Kaiin: def __init__(self, namae): self.namae = namaeclass PremiumKaiin(Kaiin): def __init__(self, namae, rank): super().__init__(namae) self.rank = rankp = PremiumKaiin("ゆい", "きん")print(p.namae)print(p.rank)実行結果
ゆい きん
06 / 07
子に __init__ を書くと、親の __init__ は自動では走らなくなる。上書きしたのだから当然だね。
super().__init__(namae) を書き忘れると、namae を入れる人がいなくなる。しかもエラーが出るのは実物を作るときではなく、使おうとしたとき。気づきにくいまちがいだよ。
class Kaiin: def __init__(self, namae): self.namae = namaeclass PremiumKaiin(Kaiin): def __init__(self, namae, rank): self.rank = rankp = PremiumKaiin("ゆい", "きん")print(p.namae)実行結果
AttributeError: 'PremiumKaiin' object has no attribute 'namae'
07 / 07
上書きするとき、super() を使うかどうかはこう考えよう。
super() は書かないsuper() を呼んでから差分を書く__init__ はほとんどの場合「足したい」ほうなので、super().__init__(...) を書くのが定番だよ。
これでクラスの道具はひととおりそろった。次は章の総合演習だ。