[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[jfriends] Re: インターフェースについて
前橋です。
>初めまして、大石と申します。
はじめまして。
>最近、Javaを勉強し始め、ようやく簡単なプログラムは組めるようになりました。
>しかしながら、いまいちインターフェースの使い道が分からず困っています。
>自分でインターフェースを記述して、インプリメントする事のメリット、若しく
>は、こんな時にインターフェースを使用すれば、効率よくプログラムを作成でき
>る等、ありましたら教えていただけないでしょうか。
遠藤さんの舌なめずりする音が聞こえてきそうな(^^;
...と思ってたのになかなか反応がないですね。
# 仕事中のメイルが禁止されたというオチでないことを祈ります。
私がJavaの勉強を始めた頃、入門書を何冊か読んだわけですが、
どれを読んでも、「Javaには多重継承がありません。だから、イン
タフェースを使います」的な書き方ばかりで、
じゃ、インタフェースってのは、多重継承の貧乏人バージョンか?
などと思ったものです。
今に至って、色々考えると、多重継承を使うところって実はそうな
いような気もしてたりするのですが。
当時、読んだ本で、「なるほど」と思った例は、
「一歩先行くインターネット Java入門」とかいう感じの書名の本
にあった、自動車とガソリンタンクの例でした。
乗り物から、自動車やら自転車やらを継承する、というのは、割と
よくある例なのですが、さらに、ガソリンスタンドで給油できるク
ラスを考えた場合、
乗り物→ガソリンを使う乗り物→乗用車
→トラック
という継承関係にすると、
じゃあ、ガソリンタンクを担いでガソリン買いに行っちゃいけないの?
ということになってしまいます(ガソリンタンクは断じて乗り物で
はない)。
こういう場合、
(1)「給油可能」インタフェースを作成し、
(2)給油可能な乗り物は、「ガソリンタンク」をメンバに持ち(コンポジション)
(3)かつ、「給油可能」をimplementsして、そのメソッドで、「ガ
ソリンタンク」にガスを入れるようにする。
わけですね。
件の本では、ここで説明が止まっています。んで、ここまで見ると、
多重継承を使っても良さそうに見えます。
インタフェースとコンポジションで実現すると、「給油可能」メソッ
ドの実装は、単に「ガソリンタンク」の「給油」メソッドを呼ぶだ
けになっちゃって、それを書くだけ面倒くさいようにも思えるので
す。多重継承があれば良かったのに。やっぱり、インタフェースっ
て多重継承の貧乏人バージョンか?
でも、継承ってのは、あくまで、is aの関係が成り立つ時に使い、
has aの場合はコンポジションで、という考え方に基けば、この例
はあくまで
「自動車」 has a 「ガソリンタンク」
であって、
「自動車」 is a 「ガソリンタンク」
ではなさそうです。
「自動車はガソリンタンクである」
と考えるより、
「自動車はガソリンタンクを保持しており、給油のためのインタフェー
スもあるよ」
と考える方が、多分自然です。
自然なだけでなく、
・ガソリンタンクをふたつ持った車
・俺の車のガソリンタンクを新型に付け替えた
などの時、多重継承では対応できませんが、インタフェースなら可
能です。ガソリンタンクがふたつあっても、給油メソッドで、まだ
空いてる方に注げばいいのです。
長くなりましたけど、まず、これが、
◎コンポジションと組み合わせる使い方
ですね。
他には、
◎複数の実装が考えられる場合
たとえば、ちょっと前に「オセロゲームの設計はどうあるべきか」
というネタをこのMLに投げたんですけど、
OthelloWindowを実現する手段としては、AWTを使ってもいいですが、
Swingを使っても、Java2Dを使っても、コマンドラインインタフェー
スを使ってもいいわけです。
こういうときは、OthelloWindowをクラスにしないでインタフェー
スにしておけば、OthelloWindowのメソッドを呼ぶ人を全然修正し
ないで、実装を差し替えることができます。
OthelloWindowを実装するクラスをnewして、オブジェクトの構造
(ポインタの張り合い)を作ってやるところまで、変更すればいいわ
けです。
この手は、「実装がまだない場合」にも使えそうです。グループで
プログラムを開発する場合、クラス毎に分担してコーディングする
のでしょうが、あるクラスのメソッドを呼ぶ人は、そのクラスのコー
ディングが完全に終了するまで書き始められない... のでは困ります。
こういう場合、先にインタフェースだけ書いとけば、それを呼ぶ人
は、まずコンパイルまではできますし(よね?)、テストする時には、
スタブ(ダミールーチン)の固まりのクラスで、そのインタフェース
をimplementsすれば良いわけです。
◎インタフェースが分類できる場合
あるクラスには10個メソッドがあるんだけど、この人が呼ぶのはそ
のうち1個だけじゃん、という場合、インタフェースに切り出せば、
関係が明示できます。
先のオセロの例だと、Board(オセロ盤)とJudge(審判)がいるんです
が、Judgeさんが知らなければならないメソッドは小数なので、イ
ンタフェースを分けました。
井浪さんのメイルにあった、自販機の例もそんな感じですね。
◎関数へのポインタ代わり
JDK1.1から、イベントモデルが変更になって、xxxListenerでイベ
ントを受けるようになりました。これは、たとえばC言語なら「関
数へのポインタ」を使うところです。
「ボタンが押されたら、このメソッドを呼んでね」
と、ボタンに対して事前に登録しておくわけです。
Javaではメソッドへのポインタはとれないので、イベントを受信す
るインタフェースを持つ(implementsしている)オブジェクトを登録
してます。
# これまた継承を使っても実現できるんですが。
他にも使用例はあると思いますが、Java初心者の私が、さっと説明
できるのは、この程度(^^;
------------------------------------------------------------
前橋 和弥 maebashi@xxxxxxxxxx
中部ソフトエンジニアリング(株)
〒450 名古屋市中村区名駅4-10-25(名駅IMAIビル 5F)
Tel:(052)583-4511(代) 内線 252 Fax:(052)583-4566
------------------------------------------------------------