Java.use(better, Python)《7》継承に警鐘を鳴らす(その漆)
|記事一覧|《こちらに移動中です》2006年6月13日 (火)
Java.use(better, Python) # Stairway to Real Agile World
《7》継承に警鐘を鳴らす(その漆)《Jython2.5.0》
■ 概要
継承の概念を実現するのに、いくつかの方法があります。そのひとつが、新しいクラスを定義するときに(2b)親子関係にないクラスのメソッドを再利用するというものです。
継承には、
(1)構造継承
(2)機能継承
(3)プロトコル継承
があって、さらに(2)機能継承は、次の3つに分類されます。
(2a)親子関係にあるクラス間の継承
(2b)親子関係にないクラス間の継承
(2c)クラスとインスタンス間の継承
ともすると、Java/C# などでは、狭義の(2a)に関心が寄せられがちです。しかし、純粋な OOP の世界では、その限りではありません。では、広義の継承は、どのように実現するのでしょうか。
《7》継承に警鐘を鳴らす(その漆)
新しいクラスを定義するときに、親子関係にないクラスのメソッドを再利用することには、どのような意味があるのでしょうか。
# Jython class Delegate: def __init__(self,delegate): self.delegate = delegate def __getattr__(self,name): return getattr(self.delegate,name)
クラス Delegate では、特殊なメソッド __init__ および __getattr__ を再定義しています。それぞれ、コンストラクター呼び出し、未定義メソッドの呼び出しに対処します。組み込み関数 getattr からは、オブジェクトの属性値が得られます。指定した文字列が、オブジェクトの属性名と一致するなら、その属性の値が得られます。
《Note》オブジェクトメソッド:__getattr__
__getattr__(self, name)属性を検索しようとして、インスタンス属性、およびクラス階層を探しても見つからないときに、呼び出されます。name は、属性名です。属性の値を返すか、例外 AttributeError を生じます。□
《Note》組み込み関数:getattr
getattr(object, name[, default])object の属性 name の値が得られます。name は、文字列に限ります。その文字列が、object の属性名と一致するなら、その属性の値が得られます。たとえば、getattr(x, 'foo') は、x.foo と同等です。その属性名がないと、与えられた default が得られます。そうでなければ、例外 AttributeError を生じます。□
# Jython m5 = Delegate(m1) m5.hello() # -------------------------------- Output -- hello, world
式 m5.hello() を評価すると、変数 m1 が束縛するオブジェクトのクラス MyObject で定義されたメソッド hello を呼び出します。すると、文字列 hello, world が出力されます。
# Jython assert m5.hello == m1.hello
式 m5.hello を参照すると、m1.hello と同じ、クラス MyObject のインスタンスに束縛された`メソッド`が得られることが分ります。
# Jython assert m5.delegate == m1
変数 m5 が束縛するオブジェクトのインスタンス辞書の中から、キー属性 delegate を参照すると、その値として、変数 m1 が束縛するオブジェクトと同じものが得られることが分ります。式 m5.hello を評価するときに、getattr(m5.delegate, 'hello') は、m1.hello と同等になります。
式 m5.hello を評価するとき、変数 m5 が束縛するオブジェクトには、インスタンス属性 hello が見つかりません。次に、クラス階層を遡って、Delegate のクラス属性を探しても、やはり見つかりません。そこで、再定義された __getattr__ が呼び出されます。
メソッド __getattr__ の定義を見ると、インスタンス属性 self.delegate をキーとする値として、変数 m1 が束縛するオブジェクトが得られます。このオブジェクトの属性名に、hello と一致するものがあるなら、その属性の値をリターンオブジェクトとします。
変数 m1 が束縛するオブジェクトのインスタンス辞書には、hello と一致するものがありません。次に、MyObject のクラス辞書を探すと、そこには、キー項目 hello に対する値として、関数オブジェクトが得られます。
《Note》文:pass
pass空文を表します。この文を実行しても何も起こりません。構文として、文が必要となる箇所で、何も実行したくないときに記述します。□
==================================
後藤いるか+伊藤うさぎ 著 ◆ 監修:小泉ひよ子とタマゴ倶楽部