- 締切済み
インターフェイス(独習JAVAのP234課題1について)
インターフェイスの参照のコーディングについて質問です interface Locomotion{ void stop(); } interface Sound{ void beep(); } abstract class Robot{ } class RobotA extends Robot{ } class RobotA1 extends RobotA implements Sound{ public void beep(){ System.out.println("RobotA1: beep"); } } class RobotB extends Robot implements Locomotion{ public void stop(){ System.out.println("RobotB: stop"); } } class RobotC extends Robot implements Locomotion,Sound{ public void stop(){ System.out.println("RobotC: stop"); } public void beep(){ System.out.println("RobotC: beep"); } } class RobotType{ private final static int NUM = 4; public static void main(String args[]){ Robot robots[] = new Robots[NUM]; Robot robots[0] = new RobotA(); Robot robots[1] = new RobotA1(); Robot robots[2] = new RobotB(); Robot robots[3] = new RobotC(); //Soundインターフェイスを実装しているメソッドの呼び出し for(int i=0;i<NUM;i++){ if(robots[i] instanceof Sound){ Sound sound = (Sound)robots[i]; sound.beep(); } } for(int i=0;i<NUM;i++){ if(robots[i] instanceof Locomotion){ Locomotion locomotion = (Locomotion)robots[i]; locomotion.stop(); } } } } main処理でSoundインターフェイス等を参照する時に、 なぜ、Sound sound = (Sound)robots[i];の用に記述しないと駄目なのでしょうか? robots[i].beep();で参照できると思ったのですが、コンパイルエラーになってしまいます アドバイスよろしくお願い致します
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- snuffy
- ベストアンサー率53% (33/62)
robots[i].beep();ではコンパイルは通りません。 robots[i]は、Robot 型で宣言されていますよね。 Robotのクラスを見ると、メソッドが定義されていないので、 つまりRobot型で宣言された参照は、見かけ上Object型のインスタンスを 参照しているのと同じことになります。 つまり、別の型にキャストしてあげる必要があります。 質問文中のような方法以外では if(robots[i] instanceof Sound){ ((Sound) robots[i]).beep(); } としても大丈夫です。 ※参考 ■配列の扱いについて Robot robots[1] = new RobotA1(); Robot robots[2] = new RobotB(); Robot robots[3] = new RobotC(); としていますが、これはコンパイルエラーになるはずです。 正しくは、 robots[1] = new RobotA1(); robots[2] = new RobotB(); robots[3] = new RobotC(); です。 ■型とクラスと変数について 型とクラスと変数の区別について、もう一度見直してみて下さい。 生成の基本形は 型 変数 = コンストラクタ(); です。 左辺は型を定義しているのにすぎないことに注目して下さい。
- takaP-
- ベストアンサー率79% (83/105)
例えば、、、日本人サッカー選手というクラスがあったとして、、 class JapaneseSoccerPlayer { public void speakJapanese(){ ............; } public void shoot(){ ............; } public void pass(){ .............; } } 日本人サッカー選手ですから、日本語も喋れますし、普通にサッカーも出来ます。 しかし、日本人サッカー選手の中にはイタリアなどに移籍したことでイタリア語を話せるようになった選手もいます。 interface ItalianSpeaker { public void speakItalian(); } class Nakata extends JapaneseSoccerPlayer implements ItalianSpeaker { public void speakItalian() { ............; } } Nakata選手はサッカーも日本語もイタリア語も出来るわけです。そして、その事実を誰もが知っています。 JapaneseSoccerPlayer pleyer=new Nakata(); この player という変数は確かにNakata選手を表しているのですから、player.speakItalian(); と、「イタリア語で話して下さい」とお願いする事が可能のように思われます。 しかし、それは貴方がplayerの実体がNakata選手だと知っているからに過ぎず、player が誰なのか知らない人々にとっては「日本人サッカー選手(JapaneseSoccerPlayer)」という提示された身分紹介以外は理解できません。 日本人サッカー選手なのだから「日本語を話せる」「サッカーが出来る」という事は身分からは推測できても、イタリア語を話せるとは夢にも思わないことでしょう。 では、どうすればいいのでしょうか。イタリア語で話せるのかを知る方法は2つあります。 1つは「貴方はイタリア語を話せますか?」と player に聞くことです。 if(player instanceof ItalianSpeaker){ ItalianSpeaker italianspeaker=(ItalianSpeaker)player; italianspeaker.speakItalian(); } 1行目が「貴方はイタリア語を話せますか?」に該当する部分です。YESならば、「日本人サッカー選手」としてではなくて「イタリア語を話せる人」として(日本人サッカー選手だからイタリア語を話せるわけじゃない)イタリア語での発言をしてもらいます。 もう1つの方法として、「貴方はNakata選手ですか?」と聞く方法です。YESならば「Nakata選手がイタリア語を話せる」ことは周知の事実ですから問題はありません。 if(player instanceof Nakata){ Nakata nakata=(Nakata)player; nakata.speakItalian(); }
- liar_adan
- ベストアンサー率48% (730/1515)
robotsはRobotの配列ですね。 この中には、Sound(を実装したもの)もあるかもしれないけど、 それ以外のものもあるかもしれません。 たとえばRobotBとか。これはSoundをimplementsしていませんね。 違うものだった場合、beep()を呼び出せません。 だからrobots[i].beep();という処理はできません。 また、一回Robotの変数に入ったものは、Soundであるかどうかわからないので、 Sound変数に代入する前に、確認のためキャストが必要になっています。 もしも別のRobot(RobotBなど)だった場合、例外が発生します。