10.3.5委譲

委譲(Delegation)は、オブジェクト指向プログラミングの概念の一つで、あるオブジェクトが持つ機能を、他のオブジェクトがそのまま利用することを指します。これは一般的に、あるクラスのインスタンスが他のクラスのインスタンスのメソッドを呼び出すことによって実現されます。

具体的な例としては、あるクラスAが他のクラスBのインスタンスを持ち、クラスAの一部の機能をクラスBのメソッドに委譲する場合が考えられます。これは継承と異なり、クラスAがクラスBの機能を再利用することができますが、クラスAはクラスBの型(subclass)ではなく、クラスBの一部の機能を使うことができるという関係になります。

委譲は、コードの再利用と可読性を向上させることができ、特に大規模なプロジェクトで役立ちます。また、クラスの関連性を疎に保つために有用であり、モジュール性と拡張性を向上させることができます。


・継承が不適切な例

リスコフの置換原則とは

「派生クラスのインスタンスは、常に基底クラスのそれと置き換え可能である」

リスコフの置換原則(Liskov Substitution Principle、LSP)は、オブジェクト指向設計の原則の一つで、1987年に Barbara Liskov によって提唱されました。この原則は、特に継承の使用において重要なガイドラインとなっています。

リスコフの置換原則は次のように述べられます:"サブタイプはそのスーパータイプと置換可能でなければならない。つまり、プログラムはそのスーパータイプのオブジェクトをサブタイプのオブジェクトと置換しても正しく機能し続けるべきである。"

具体的には、あるクラスBがクラスAを継承している場合、クラスBのインスタンスはどのような状況でもクラスAのインスタンスとして扱うことができるべき、ということを指します。これは、派生クラスが基底クラスと同じ振る舞いを保証することを意味します。この原則を遵守することにより、継承の混乱を避け、コードの再利用性を向上させることができます。


教科書に例が書いてあるのですが、中略あるので、今の私では、際限ができないのでカット

・委譲による解決

>>> class MyStack:
...     #委譲先のオブジェクトを変数に保持
...     def __init__(self):
...         self.__data = []
...     # pushメソッドとpopメソッドをクラス内に定義
...     def push(self, elem):
...         self.__data.append(elem)
...     def pop(self):
...         return self.__data.pop()
...
>>> if __name__ == '__main__':
...     s = MyStack()
...     s.push(40)
...     print(s.pop())
...     print(s)
...
40

教科書上ではdefが三つあるのですが、それぞれの間に改行されており、そのままだとエラーがでるので

無くしたところ、エラーがなくなりました。
  1. 1.最初に、MyStackという名前のクラスを定義しています。このクラスには__init__pushpopという3つのメソッドが定義されています。


  2. 2.__init__
    メソッドは、クラスのインスタンスが生成されるときに呼び出される特殊なメソッドです。ここでは、新しいインスタンスが作成されるときに、空のリストを__dataという名前のインスタンス変数に割り当てています。このリストは、スタックに要素を追加したり削除したりするために使用されます。


  3. 3.push
    メソッドは、引数として与えられた要素をスタック(__dataリスト)の最後に追加します。これはPythonのリストのappendメソッドを使用して実現されています。


  4. 4.pop
    メソッドは、スタック(__dataリスト)の最後の要素を削除し、その要素を返します。これはPythonのリストのpopメソッドを使用して実現されています。


  5. 5.if __name__ == '__main__':
    により、このスクリプトが直接実行されたときにのみ、次のコードブロックが実行されます。


  6. 6.MyStackクラスの新しいインスタンスsを作成しています。


  7. 7.s.push(40)
    により、40という要素をスタックsに追加しています。


  8. 8.print(s.pop())
    により、スタックsから最後の要素を削除し(この場合は40)、その要素を表示しています。


  9. 9.最後にprint(s)により、スタックsの現在の状態を表示しています。popメソッドにより要素が削除された後なので、このスタックは空([])になっています。