継承の問題点

2週間ほど前にGois Godを始めて、言語の特徴として継承がないことに驚いた。
今まで触れてきた言語は皆オブジェクト指向で継承システムを有していたので、新しい言語(2000年以降に開発された言語を指す)が継承をサポートしていないことに違和感を覚えたのである。

しかし、Goの理念やオブジェクト指向について理解を深めていくうちに、継承というシステムにいかに問題点が多いか気づかされ、自身の浅慮を思い知った。

  • 継承の問題点

自分はまだまだ未熟で大きな声では言えないが、継承が「共通部分を再利用するためのシステム」という認識は「誤った認識」だと考えている。
入門書(入門サイト)がどのように継承を解説しているか十分な調査はしていないが、私が初学時に得たのはこの認識であった。

スーパークラス(親クラス、継承元)の設計は、サブクラス(子クラス、継承する側)の性質から抜き取ってはならないはずだ。
後々サブクラスと同列のクラスの実装を行う際、そのような設計を行っているとス―パークラスも書き換えなければならないからだ。
実際にはスーパークラスの書き換えが行われず、余計な機能が継承されてバグや解読不能なコードになっているのだろう。

DogクラスとCatクラスを実装するからAnimalを実装するというのはやってはいけないのである。
初めにAnimalクラスが要請されて、その後Dogクラスが要請されたならばDogクラスはAnimalクラスを継承すべきだろう。

犬と猫は走る
→おそらく動物には足があるだろうと、Animalクラスで足を追加
→後々蛇クラスの実装が要請されてAnimalクラスを継承
→足のある蛇の完成 or Animalクラス及びそのサブクラスの変更要請

帰納から"真のスーパークラス”を作成するのはリスクの高い作業なのである。
継承の本質は演繹なのだ。
しかし、既存の継承には帰納からの設計を制限する機能はない。

  • 共通部分の切り出し

具体例が追加されて共通部分が発生したならば、その部分を関数で切り出してしまえば良い。
最近はこの考えのもとプログラミングを行っている。

継承はメソッド存在の保証(抽象基底クラス)や独自の名前でラップするのに利用している(同じint型でも、それがIDを指すのか、重さを指すのか等を変数名ではなく型として書くため)。

Goではメソッド・プロパティの存在保証はインターフェイスによって行われる。