インターフェイスとは

前回(クラスとは)はclassとは何かを考えてみたので、今日はinterfaceについて考えてみる。

インターフェイスとは、オブジェクトのに付与される性質の1つである。

クラスとは、同じ性質を持ったオブジェクトを分類 (classification) したものです。同じメソッドを持っていて、それらが似たような振る舞いをするオブジェクトが同じクラスに属していると言われます。

クラスに属するオブジェクトが共通して持っている性質は同じメソッドをもっているだけではありません。同じインターフェイスを実装しているという性質も共通しています。同じインターフェイスを実装すれば、結果として同じ名前のメソッドを持つことになりますが、同じインターフェイスを持つということの方が狭い意味になります。ただのメソッドよりインターフェイスを実装しているメソッドの方が特殊ということです。

Car, Fugitive(逃亡者), Procedureというクラスがあって、どれも run() というメソッドを持っているとしましょう。これらのメソッドは同じ run という名前ですが、クラス名から考えると全く別の意味になるでしょう。

f:id:fjkz:20160414193246p:plain

メソッドの意味は文脈で決まります。クラス名から推測すると、Car::run() は「走る」、Fugitive::run() は「逃げる」、Procedure::run() は「実行される」という意味になるかと思う。

これらのメソッドが Runnable インターフェイスを実装していたら、全く意味合いが異なってくる。runメソッドの処理がスレッドに乗せて実行できるという意味になる。(不自然極まりないが)

f:id:fjkz:20160414193840p:plain

このようにインターフェイスメソッドに文脈を与えることできる。たとえ違うクラスのメソッドであっても、それらが同じインターフェイスメソッドであれば、同じ意味になる。

インターフェイスとは、クラス間で共通した意味合いのあるメソッドの集合のことである。インターフェイスメソッドが1つの場合もあるし、複数の場合もある。

ダック・タイピングができるプログラミング言語では、Runnable インターフェイスを継承していなくても、Car, Fugitive, Procedureのrun メソッドは同じ意味とみなされる。意味が違うものにたまたま同じ名前がついていても、同じ意味として実行されてしまう。間違った使い方をしていないかどうかは使う側が気をつけるなければならない。

Javaの場合は、異なるクラスの間でも共通の意味のあるメソッドインターフェイスとすることで、かちっとした文脈を与える。プログラム上での文脈だとか意味だとかはしばしば「型」と呼ばれる。

メソッドを持たないインターフェイスというものもある。例えば、ClonableとかSerializableとかだ。これらも、メソッドはないけれども、オブジェクトに性質を付与するものだ。*1

クラスは同じ性質をもつオブジェクトの分類だが、インターフェイスとはオブジェクトの性質である。抽象クラスはクラスだ。したがって、抽象クラスとインターフェイスは、使い方は似ているが、使い道や意味が全く異なるものであるといえる。

では、インターフェイスがオブジェクトの性質で、クラスが同じ性質を持つオブジェクトと集まりというならば、同じインターフェイスを持っているオブジェクトは同じクラスであると言えるのではないかという疑問も湧いてくる。

我々の住む世界ではそれは可能だ。青い車、青い空、青い鳥といった異なるクラスに属するものを集めてきて、青いものという別のクラスをつくることはできる。

しかし、プログラムの世界ではそれはできない。1つの理由は単にJavaが多重継承を認めていないという理由だ。もう1つの理由は前回書いたが、プログラムの世界は似たようなオブジェクトを集めて分類してクラスを作るのではなく、クラスが先にあるからだ。あとから分類することは無理なのです。

青いものクラスの世界をつくるべきなのか、車クラスの世界をつくるべきなのかは「場合による」。それを決めるのが設計なのです。

*1:アノテーションがないころの名残なので、今インターフェイスをこのように使ってはいけない。