抽象クラスとインタフェースの違い

間が空いてしまったけれども気を取り直して。懲りずにJAVAWORLD、もう12月だと言うのにまだ11月号だ。今回の内容は抽象クラスとインタフェースの違いについて。常識なのかも知れないけど考えたこともなかったのでメモ。
JAVAでクラスの多重継承ができないのは有名な話。extendsはひとつだけ。でもimplementsは複数出来る。多重継承ならぬ多重実装。じゃあインタフェースはクラス多重継承できないけどやりたい!って時に使うもんなの?という話。
ここで「継承」には大きく分けて2つのメリットがある。それは「型の継承」と「実装の継承」。これらは一括りに「継承」と扱われることが多いけど、分離させて認識する必要がある。ここで例えば以下のような継承の例を考える。

class A {
	public void method1(){/* A hogehoge */}
}

class B extends A {
	public void method2(){/* B hogehoge */}
}

このときクラスBのインスタンスはクラスA型のインスタンスとして扱うこともできる。つまり、

A hoge1 = new B();

と書ける。これはクラスBがクラスAの「型」を継承しているから。じゃあ「実装の継承」は何なのかと言うと、

B hoge2 = new B();
hoge2.method1();

という風にクラスAのメソッドを呼び出せること。クラスBにはmethod1()が定義されていないのに呼び出せる(/* A hogehoge */ の部分の実装を使える)。これが「実装の継承」に当たる。一方、ご存知の通りインタフェースには実装は記述しない。こんなメソッドあるよ、って言う「型」だけ記述する。なのでインタフェースのimplementsは「型の継承」に当たる。ほんで多重継承したい!って時にやりたいのは「型の継承」のはずなので、クラスは多重継承できなくて良いでしょ、インタフェースでやればいいでしょ、というお話でした。

ほいでまずこの話、「型」だの「実装」だのの言葉が飛び交っててややこしい。インタフェースの所なんか日本語で書くと「インタフェースを実装することで「型の継承」を行う」とかなってややこしいにもほどがある。これはいったいどうなっとんのかと思い、ちょいと調べてみたところ「型の継承」「実装の継承」という言葉は「オブジェクト指向とはほにゃらら」みたいな時に普通に出てくる単語の模様。仕方ないのでそのまま受け入れることに。
ちなみにこの話も実はあれこれ議論されてる話のようで「多重継承しないことにしたからインタフェースをサポートしたんだ!」とか「インタフェースをサポートしたから多重継承を禁止できたんだ!」とか、なんか宗教戦争くさい雰囲気もちらほらと…*1。たしかにこの理屈で行くと、abstract classの存在って何なんだよ?ってなっちまう気もしたり。でも「いやいや!それにはそれで意味がある!」みたいな感じでめっさややこしそうでしたので、とりあえず今日はここまで。

*1:そんなこと言っちゃダメだよね、みんな真剣なんだからね。すいません。