《10》クラスに頼らない OOP(4)〈Python 3.0 版〉

Previous| |Next
Python à la carte記事一覧
《10》クラスに頼らない OOP(4)

《著》小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第1版♪2003/05/25 ● 第2版♪2004/06/01 ● 第3版♪2009/02/28

関連記事

なぜクラスが必要なのか

クラスに頼らなくても、インスタンスオブジェクトに固有の状態を保持したり(クラス継承に代えて)機能を拡張/変更できるのを実証しました。では、なぜクラスが必要なのでしょう。その理由を明らかにする前に、ここまでの例題の問題点を解消しておきます。

クラス継承に代えて

前述した例題 ex4/ex5 では、インスタンスオブジェクトを生成した後で、個別に機能を追加(拡張/変更)できるという利点があります。しかし〈例題 ex3〉のように、同じ機能を持つ複数のインスタンスが必要になる状況では、逆にそれが欠点になります。なぜなら、新たなインスタンスを生成するたびに、既存の(継承した)機能を追加する必要があるからです。

この問題を解決するには、共通する機能を再利用するとともに、個別の問題解決にも対処できるような工夫が必要になります。その選択肢のひとつとして、差分プログラミングを支援する「クラス」が注目されたわけです。しかし、それを実現するだけなら、クラスに頼らなくても可能です。

■ 機能の拡張

前述した〈例題 ex4〉では、新たな機能 top を追加するのに、生成したばかりのインスタンスに新たな属性を設定しました。しかし、そのたびに同じ設定をするのは面倒です。そこで、

def XStack():        # class XStack(Stack):
    self = Stack()
    self.top = lambda: top(self)
    return self

関数 Stack を再利用するとともに、その機能を「拡張」するのに、インスタンス属性 .top に(クロージャーとしての)lambda 関数を設定します。self の値は、lambda 関数を定義するときに解決するので、XStack のインスタンスに固有の関数(メソッド)になります。すると、次のように、

def ex6():
    stack = XStack()    ;print(stack)
    stack.push("A")     ;print(stack)
    s = stack.top()     ;print(s)
    stack.push("B")     ;print(stack)
    s = stack.top()     ;print(s)
    s = stack.pop()     ;print(stack,s)
    s = stack.top()     ;print(s)

追加した関数 top を利用して、

>>> ex6()
[]
['A']
A
['A', 'B']
B
['A'] B
A

スタックの最上位にある値を参照できるのが分かります。

■ 機能の変更

前述した〈例題 ex5〉では、既存の機能 top を変更するのに、生成したばかりのインスタンスに新たな属性を設定しました。やはり、そのたびに同じ設定をするのは面倒です。そこで、

def IntStack():        # class IntStack(Stack):
    self = Stack()
    self.push = lambda item: push_int(self,item)
    return self

関数 Stack を再利用するとともに、その機能を「変更」するのに、インスタンス属性 .push に(クロージャーとしての)lambda 関数を設定します。self の値は、lambda 関数を定義するときに解決するので、IntStack のインスタンスに固有の関数(メソッド)になります。すると、次のように、

def ex7():
    stack = IntStack()  ;print(stack)
    stack.push(1)       ;print(stack)
    stack.push("2")     ;print(stack)
    stack.push(2)       ;print(stack)

変更した関数 push を利用して、

>>> ex7()
[]
[1]
stack expected 'int' item, got '2'
[1]
[1, 2]

スタックには整数以外の値を積めなくなるのが分かります。

Tips

共通する関数 Stack をもとにして、その機能を拡張した XStack や、その機能を変更した IntStack など、クラスによって支援される「差分プログラミング」の特徴は、クラスに頼らなくても実現できます。

Last updated♪09/03/25