人生最悪の忘れ物

インターフェイスを実装したクラスの型変換ができるのはなんでですか?
例えば、

interface Drinks{
void print();
}

class Tea implements Drinks{
int money;
Tea(int money){
this.money = money;
}
void print(){
System.out.println(money +"円");
}
}

class Inter{
public static void main(String[] args){
Drinks drinks = new Tea(200);
Tea tea = new Tea(200);
drinks.print();
tea.print();
}
}

の様なコードがあったとして
Drinks drinks = new Tea();
はなんかおかしく感じるのですが。。
Tea型のクラスとして生成されたインスタンスが、インターフェイスであるDrinks型の変数drinksに代入できるということは、変数drinksは、Drinks型でありTeaクラスの実体を参照できるということですか??
そして
drinks.print(); と tea.print(); の違いがはっきりとわからないんですが、よろしくお願いします!

ちなみにコンパイル通してないんで実行できるか確かではないですが言いたいことが伝わればいいのでそこんとこよろしくお願いします!

A 回答 (3件)

# おいらはC#のinitiateに過ぎないし、C#とJavaとはことなるところもあるだろうけど、インタフェースについては似たようなものだと思うので書いてみる。



インターフェースというのはC++における純粋仮想関数のみで構成される抽象クラスと考えるべきだというのをどっかで読んだことがあるなぁ。

Drinkというインターフェースは「飲み物」という抽象的な性質・特性をあらわしていて、それを特徴付けるものが定義されているメソッド。
Drinkを実装するクラスは「飲み物」という特性を持っているということになる。

Drinkを実装しているクラスのインスタンスをDrink型の変数に代入すると、それはDrinkとしか扱われないというのが重要なんだと思う。Drinkで定義されているメソッド(操作)のみが見えている。

よりわかりやすいのが、インタフェース型を引数としてとる関数かも知れない。
Drink型の引数にはDrinkを実装したクラスの変数を渡すことが出来る(はず)。
つまり、「飲み物」ならばソフトドリンクであろうがアルコール飲料であろうが何でも受け付けて、その関数の中では(原則的に)インタフェースに定義されたメソッドを使って処理が行われる。
繰り返すようだけど、同じ性質・特性・概念を持つものを統一的に扱うことが出来るってことだろうかと。
# ただ、これが上手くできるようにするにはインタフェースにどのようなメソッドを定義するかを十分に考えてやらないといけないんだろうけどね。

この回答への補足

返事が遅くなりましたが、なるほどです。参考になります!
つまり車で例えると、基本はエンジン、ボディー、タイヤがすべてに共通するものであり、それらをインターフェイスのメソッドとするならば、
多種ある車ごと(car1,car2,...,carnとおく)のクラスがあり、それらの車のクラスで、エンジンの排気量や静音性や熱効率、ボディーの形状や色、タイヤの摩擦や大きさといった特性を定めることになる。ということですよね。
プログラム上ではcar1をインターフェイスに渡すということはcar1型という仕様書を生産工場に渡すということなんですね。
つまりどんな型でも受け入れられる抽象型がインターフェイスといった感じですか。

補足日時:2009/12/20 15:19
    • good
    • 1

一つ思いついたんだけどね。



上手く使うと、コンパイル時の型チェックで、ファンクションなどに変なパラメタを渡す等のエラーが減ったりするんじゃないかなぁって。

あなたの例だと、飲み物でない値を飲み物を扱うファンクションに渡そうとするとコンパイルエラーが発生すると。


あと、個人的にはprint()なんていうメソッドをインタフェースに入れているのはどうかと思う。それはメインの継承の軸の方に入れるべきでは無かろうかと。(おそらくは大本のクラスに)
インタフェースにはそのインタフェースが示す概念と切っても切り離せないものを宣言しておくべきであろうかと。
# 「表示する」というのが「飲み物」という*概念*に近接しているとはとても思えない。
もしかすると、そんなクラス・インタフェース設計を例として使っちゃったところが、理解を妨げてしまっているのではないかとも思える。
    • good
    • 0

>変数drinksは、Drinks型でありTeaクラスの実体を参照できるということですか??



そうですね。「お茶」は「飲み物」として扱うことができると考えることができます。

>drinks.print(); と tea.print(); の違いがはっきりとわからないんですが、よろしくお願いします!

動作の実態は同じです。
「飲み物」として扱うか、「お茶」として扱うかの違いになります。

プログラム上では、より汎用的な「飲み物」として扱うことにより、
状況に応じて「お茶」や「コーヒー」等を扱うことができることになります。
「お茶」と特定せずに「飲み物」とすることで、扱う品目を容易に増やしたり、
別の飲み物に対応させたりすることが可能になります。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
つまりインターフェイスであるDrinksは可変的で柔軟だから、それを実装するクラスはDrinks型に型変換できるというイメージでいいんでしょうか。。

お礼日時:2009/12/08 00:53

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報