山下寛人オフィシャルブログ

オイシックス株式会社 執行役員 システム本部長 山下寛人の公式ブログです。

継承のデメリット

前も同じことを書いたような気もしますが

googleで検索しても出てこないので書きます。

継承を覚えると使ってみたくなりますが、

実は継承はかなりうまく作らないと逆に苦労します。


ただ差分プログラミングをしたくて継承して

しまうと、子クラスのソースを読んだだけでは

何をしているのかさっぱりわからないソースに

なってしまいます。

親クラス、下手をするとその親とかもっと親まで

読みにいかないといけなくなります。

まるで迷路のような。

スパゲッティです。


また親クラスの変更の影響が予測しにくくなります。

クラスを外部から使っていればインターフェースを

同じにしておけば大丈夫なのですが継承だとそうは

いきません。

結果として親クラスの変更が怖くてできなくなり、

いびつな拡張をせざるを得なくなります。

カプセル化を破壊するということです。


基底クラスを作っていろんなクラスで継承するような

パターンだと、基底クラスが肥大化します。

なんか共通に使いそうなものを何でもつっこんで

いってしまいます。

するとその機能を利用するには継承しないといけなく

なりますが、Javaだと多重継承ができないので

利用できないケースが出てきます。

使いまわしがしにくくなります。

じゃあそれらの機能が本当に全部基底クラスにあるのが

ふさわしいかというと、そんなことはありません。

むしろ整理するといろいろな役割にグルーピングできます。

となると、そのグループ分けごとにクラスを作ったほうが

いいはずです。


これらをふまえると継承をする際にはかなりしっかりとした

モデリングが必要ということになります。

差分プログラミングだけでなく、概念としてis-aの関係で

あること。

また親と子の責務の分担が明確になるように設計する

必要があります。


よい例としては、HttpServletがあります。

HttpServletは親と子の役割が明確なので、子クラスを

作るとき親クラスのソースを知らなくてもよいし、

サーブレットコンテナの作成者は子クラスを気にせず

いろんな実装をしたり機能拡張をすることができます。


でも、そこまで考えて設計できる人は非常にまれです。

そこまでして継承を使わないといけない場面があるかと

いうと、普通ありません。

共通機能は共通機能のクラスを作ってnewしたり

staticメソッドで使えばいいのです。

世の中の流れ的にも継承だと単体テストがしにくいので

継承を使わずアノテーションを使う方向に進んでいます。

ということで、基本的に継承は使わないルールに

してしまうのが一番簡単ではないかと思います。