《余録》継承の隘路 - 継承は必要悪か
Java プログラマーのための Python 導入ガイド《記事一覧》
《余録》 継承の隘路 - 継承は必要悪か
■ 概要
特殊メソッド __getattribute__ を利用すると、「継承の問題点」を回避する、新たな方策が可能になります。
OOP の黎明期には脚光を浴びた継承も、やがて、さまざまな問題点が指摘されることになります。 その反省から、継承から委譲へとパラダイムシフトが起こりますが、では継承は「必要悪」なのでしょうか。 継承は「必要悪」委譲は「救世主」とするステレオタイプには「再」再考の余地があります。 《Note》JPython1.1.x/Jython2.1.x 用に作成したセミナー課題を、Jython2.5 で再構成しました。
■ 関連記事
- GoF を反面教師に, Adaptor
参考文献 | note |
---|---|
JavaプログラマのためのUML活用ガイド―例題に学ぶオブジェクト指向プログラミング設計
|
「継承」の問題を回避するために「委譲」を活用する方法を紹介しています。 |
背景
Python 2.3 以降になると、新たなクラス体系を支援する、特別なメソッド __getattribute__ を利用できます。すると「継承の問題点」を回避する、新たな方策が可能になります。そこで、今回は「委譲」が抱える問題を回避するために、再び「継承」を取り上げることで、継承の本質に原点回帰します。
OOP の黎明期(1970 年代)には「継承」はそれを支える三本柱のひとつとして脚光を浴びました。
しかし、技術的には未成熟な部分が多く、1980 年代になると、その問題点が指摘されるようになります。
スリーアミーゴのひとり(後に UML に強く影響を与える)Rumbaugh さんの著書(1991 年)でも
「継承の問題点」が指摘されるなど、継承に「警鐘を鳴らす」いくつかの論文が発表されます。
1990 年代になると、継承の問題を回避する救世主として「委譲」へのパラダイムシフトが広く認知されるようになりました。
「デザインパターン」が一般にも認知される契機となった、GoF の著書(1995 年)にも、その問題を回避する手法が紹介されています。
同じ年に発表された Java を初め、その後の C# など、新たに考案された OOP 言語が、
継承に代わる委譲を強力に支援することで、差別化を図るかのように進化していったという歴史があります。
そして、Python/Ruby など、より本格的な OOP 言語が普及し始めると、Java/C# にはない強力な支援機能によって、
再び継承の持つ本来の意義が見直されています。
歴史は繰り返すという言葉があります。
技術の進歩が価値観を一変させ、一度否定されれた技術が再び脚光を浴びるなどは、歴史を紐解くまでもありません。
Python の強力な支援機能を利用して「継承」の問題点を回避する方法について再考します。
⇔ 承前 》何が問題だった《 のか:継承に継承を鳴らす
⇔ 承前 》何が問題だった《 のか:継承が抱える深刻な問題
⇔ 承前 》何が問題だった《 のか:委譲による問題回避
事例:スタックを実現する
組み込み型 list の動作を「継承」によって、自由に拡張/抑制できます。そこで、list の機能を再利用するとともに、スタックを実現するのに必要のない機能はすべて無効にします。
■ 機能の抑制
特殊なメソッド __getattribute__ は、任意の属性へのアクセスを横取りして、ドット「.」による値の参照/変更、メソッド呼び出しなどを自由に制御できます。
class Stack(list): def __getattribute__(self, name): dirs = { "push": "append", "pop" : "pop" , } name = dirs.get(name) if not name: raise AttributeError return list.__getattribute__(self, name)
クラス Stack は、組み込み型 list を継承したにも関わらず、メソッド push/pop 以外をすべて無効にします。メソッド push は、既存のメソッド append を再利用します。また、メソッド pop は、既存のメソッド pop の動作を、次のように変更します。
■ 機能の拡張(変更)
継承によって、既存のメソッドの動作を自由に拡張できます。
def pop(self): try: return list.pop(self) except: return None
メソッド pop は(組み込み型 list とは違って)空のリストに対して例外を生成せずに、None をリターン値にします。
⇒ 続きはこちら 》《余録》継承は必要悪か __getattribute__《 で