2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

私がオブジェクト指向を勉強するにあたって役立った講座三部作を書く。
これらの講座を作ったのはピーコック アンダーソンである。

これらを学ぶと、オブジェクト指向において陥りがちなミスに対して、適切に対応することが可能である。

よくありがちなミスが、Aという具象クラスを継承して拡張し、Bというクラスを作るというもの。これのどこがまずいかというと、BはAとしても振る舞える必要がある(リスコフの置換原則)が、それが壊れるからである。

こういう問題が起きないパターンとしては、Aがインタフェースであるか、抽象クラスであり、かつAの具象メソッドをオーバーライドしていない場合である。この場合、Bに期待されるのは、Aの抽象メソッドがこう振る舞うべきであるという規定通りに動くことである。

from abc import ABC, abstractmethod

class A(ABC):
    """抽象クラス"""
    @abstractmethod
    def f(self, i: int) -> int:
        """整数に何らかの加工を行って返します."""
        pass

class B(A):
    """具象クラス"""
    def f(self, i: int) -> int:
        """整数に2倍して返します."""
        return i * 2

c: A = B()
print(c.f(3))

例えば、これはこの原則に従えば正しいことは明らかだろう。ところが、例えばAが具象クラスであり、fがiを3倍して返す関数だったとしたらどうだろうか?容易に想像がつくが、3倍して返す関数であるという挙動を想定してプログラムを組んでしまい、容易に破綻するのである。

ほかにも、抽象に対してプログラミングすべき、という規則もある。全部具象クラスで組むのであれば、継承という概念は無意味であるのだから当然である。

例として、DbStorageというクラスはIStorageというインタフェースを実装しており、データベースに接続して値を取得して返す仕組みであるとする。この場合、DbStorageは具体的にデータベースに接続して値を取得するわけだが、DbStorageに依存して組んでしまうと、データベースに接続しないとテストもできないし、データベースの中身に応じて動きが変わってしまうなどの問題が発生する。このため、MockStorageという、別のIStorageを実装したクラスを用意して、IStorageの想定通りに振る舞うようにすると、テストがやりやすくなるため、非常に便利になるのだ。

もしかしたら少し上級者向けかもしれないが、受けてみるのは一つの手段だろう。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?