Python3の復習(ポリモーフィズムとダックタイピング)
こんにちは。
アニメ欲が溜まっていている、かにたまごです。
アニメじゃなくて何故かYouTubeでくだらない(申し訳ないけど)動画ばかり観てしまう(;^ω^)
今期はなにやってるんだろ・・・。
それはさておき、今回は
- ポリモーフィズム
- ダックタイピング
について、復習していきたいと思います。
前にチラッと見たことあったけど、「いや、まだ使わんだろ」と思って飛ばしてたとこ。
今はとにかく「使うとしたらどう使うか」を考えることが大事だと思っているので、勉強していきます。
今までのPython3 復習履歴は以下の通り。
- 数値・文字列
- リスト・タプル
- 辞書・集合
- if文・while文・for文
- 内包表記
- 関数
- ジェネレータ
- デコレータ
- 名前空間とスコープ
- アンダーバー・アンダースコアの意味
- エラー処理:try・except
- モジュール・パッケージ
- 標準ライブラリ
- オブジェクトとクラス①-クラスの定義-
- オブジェクトとクラス②-継承-
- プロパティ
ポリモーフィズム
参考書見てもよく分からなかったので、色々調べた。
言葉の意味。
これはweblioに載ってた以下の文で何となく理解できた。
ポリモーフィズムは、オブジェクト指向設計の原則である「機能と実装の分離」を実現するために欠かせない機能で、オブジェクトを呼び出す側が意識しなくても実行時の条件に合った適切なメソッドが実行できる。ポリモーフィズムは、継承を利用しているため、オーバーライドと同様な機能に見えるが、ポリモーフィズムの場合は機能が置き換わるのではなく、同一名称メソッドであるが振る舞いは異なるメソッドとして働く。
その他どういう場面で利用されるかなどは、この記事の最後に載せたサイトを参考にした。
とりあえず何となくは理解できた。が
「オーバーライドと何が違うの・・・?」
うーん。
とりあえずコードを書いてみる。
class Idol(): def __init__(self, song): self.song = song def sing(self): print("{} を歌ってもらいましょう".format(self.song)) class MorningMusume(Idol): def sing(self): print("続いては モーニング娘。 に歌ってもらいましょう。\n{}".format(self.song)) class Cute(Idol): def sing(self): print("続いては ℃ute に歌ってもらいましょう。\n{}".format(self.song)) class BerryzKobo(Idol): def sing(self): print("続いては Berryz工房 に歌ってもらいましょう。\n{}".format(self.song)) class Nogizaka46(Idol): def sing(self): print("続いては 乃木坂46 に歌ってもらいましょう。\n君の名は希望".format(self.song)) idol = Idol("赤いスイートピー") idol.sing() musume = MorningMusume("LOVEマシーン") musume.sing() cute = Cute("まっさらブルージーンズ") cute.sing() kobo = BerryzKobo("スッペシャルジェネレ~ション") kobo.sing() nogi = Nogizaka46("君の名は希望") nogi.sing()
赤いスイートピー を歌ってもらいましょう 続いては モーニング娘。 に歌ってもらいましょう。 LOVEマシーン 続いては ℃ute に歌ってもらいましょう。 まっさらブルージーンズ 続いては Berryz工房 に歌ってもらいましょう。 スッペシャルジェネレ~ション 続いては 乃木坂46 に歌ってもらいましょう。 君の名は希望
上記のコードでは、各クラスでIdolクラス を継承して sing() をオーバーライドしている。
この同名のメソッドをオーバーライドして、クラスごとに異なる振る舞いをさせる性質をポリモーフィズムと呼ぶのかな。
・オーバーライド = 親クラスを継承して、子クラスで親クラスのメソッドを上書きすること
・ポリモーフィズム = オーバーライドを利用して、同名メソッドで異なる振る舞いをさせる性質
オーバーライドが機能で、その機能を利用して成り立つ性質をポリモーフィズムと呼ぶ
この認識で大丈夫かな・・・?
ダックタイピング
こちらも意味的な理解はWebサイトにお任せ。
ダック・タイピング(duck typing)とは、Smalltalk、Perl、Python、Rubyなどのいくつかの動的型付けオブジェクト指向プログラミング言語に特徴的な型付けの作法のことである。それらの言語ではオブジェクト(変数の値)に何ができるかはオブジェクトそのものが決定する。つまり、オブジェクトがあるインタフェースのすべてのメソッドを持っているならば、たとえそのクラスがそのインタフェースを宣言的に実装していなくとも、オブジェクトはそのインタフェースを実行時に実装しているとみなせる、ということである。
つまり、継承を利用してオーバーライドせずとも、インターフェースから呼び出される関数を持つクラスを定義しておけば大丈夫ってこと?
Idolクラスを継承していない新しいクラスを定義する。
記述したコードは全てsing()を持つので、who_sing というインターフェースから呼び出せるはず。
class Idol(): def __init__(self, song): self.song = song def sing(self): print(" {} を歌ってもらいましょう".format(self.song)) class MorningMusume(Idol): def sing(self): print("続いては モーニング娘。 に歌ってもらいましょう。\n{}".format(self.song)) class Cute(Idol): def sing(self): print("続いては ℃ute に歌ってもらいましょう。\n{}".format(self.song)) class BerryzKobo(Idol): def sing(self): print("続いては Berryz工房 に歌ってもらいましょう。\n{}".format(self.song)) class Nogizaka46(Idol): def sing(self): print("続いては 乃木坂46 に歌ってもらいましょう。\n{}".format(self.song)) class Kiyo(): def __init__(self, song): self.song = song def sing(self): print("尾崎紀世彦さんに歌ってもらいましょう。\n{}".format(self.song)) def who_sing(obj): obj.sing() idol = Idol("赤いスイートピー") #idol.sing() who_sing(idol) musume = MorningMusume("LOVEマシーン") #musume.sing() who_sing(musume) cute = Cute("まっさらブルージーンズ") #cute.sing() who_sing(cute) kobo = BerryzKobo("スッペシャルジェネレ~ション") #kobo.sing() who_sing(kobo) nogi = Nogizaka46("君の名は希望") #nogi.sing() who_sing(kobo) kiyo = Kiyo("また逢う日まで") who_sing(kiyo)
赤いスイートピー を歌ってもらいましょう 続いては モーニング娘。 に歌ってもらいましょう。 LOVEマシーン 続いては ℃ute に歌ってもらいましょう。 まっさらブルージーンズ 続いては Berryz工房 に歌ってもらいましょう。 スッペシャルジェネレ~ション 続いては Berryz工房 に歌ってもらいましょう。 スッペシャルジェネレ~ション 尾崎紀世彦さんに歌ってもらいましょう。 また逢う日まで
オブジェクトが振る舞う動作は、インターフェースが実行されたときに決まるってことか・・・な?
最後に、合ってるかどうかわからないけど自分の中でスッキリさせるために図を描いた。
ポリモーフィズムを実現させるには継承を利用してオーバーライドする方法、継承を利用せずダックタイピングする方法の二つの手法がある
の図。
これで一応納得できた。
ポリモーフィズム・・・難しい概念。
これで理解できた気はするから、どんどん活用して理解を深めていこう。
以上です。
参考にさせていただいたサイト:
プログラマー1年生がポリモーフィズムについて学んだのでRPGで説明する。