- ベストアンサー
データ型で質問です。
JAVA勉強中のものです。 データ型で質問があります。 class Animal{ public void run(int speed){ System.ou.println("My animal is running"); } } class Dog extends Animal{ public void run(long speed){ System.out.println("My dog is running"); } } class Test{ Public Static void main(String args[]){ Animal myAnimal = new Dog(); -----* myAnimal.run(5); } } 出力結果は My animal is running になりますが、わかりません。 *行は実際のオブジェクトはDog型で,次のmyAnimal.run(5)は インスタンスメソッドなので、オブジェクトのDogを見に行くと 思うのですが、違うのですか? 本に書いてあったので解説お願いします。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
日本語が下手で申し訳ないです。 まず、ご質問者さんの本当の意味での質問 「myAnimal.run(5)はインスタンスメソッドなので、 オブジェクトのDogを見に行くと思うのですが、違うのですか?」 は、正しいです。 インスタンスとしてのDogオブジェクトを見に行っています。 ところで、今回の場合、Animalクラスに代入されています。 そのため、DogオブジェクトインスタンスをAnimalオブジェクトとしてメソッドを実行します。 >変数の型で見に行くのですか? >(見当違いな質問ならすいません) これは、「オーバーライド」と「オーバーロード」の話になります。 まず、「インスタンスとしてはDogしかない」というのはOKですよね? ここで、DogオブジェクトはAnimalオブジェクトを継承していますので、 DogオブジェクトはAnimalオブジェクトとしての機能は全て持っています。 Dogオブジェクト内では、runメソッドが再定義されていて、 引数がlongとintと違うため、「オーバーロード」が発生していますので、 2つのrun()メソッドを持っていることになります。 今回の場合、DogオブジェクトをAnimalオブジェクトとして見ているので、Dogオブジェクト内のAnimalオブジェクト部分しか見えません。 Animalオブジェクトに引数long型のメソッドが無い以上、呼び出すことはできません。 もし、ここで Animalオブジェクトも引数の型がlongだったとすると 今度は「オーバーライド」が成立します。 この場合、『Dogオブジェクトのインスタンスで同じメソッドが上書きされている』 状態になるので、AnimalオブジェクトとしてDogオブジェクトを見ても 「myAnimal.run(5);」の結果は『"My Dog is running."』になるのです。
その他の回答 (6)
- PED02744
- ベストアンサー率40% (157/390)
ANo.3です。 追追伸:(一度に書けよ>自分、ごめんなさい>みなさま) Animal myAnimal = new Dog(); -----* こっちをそのままにしたいのならば、クラスキャストをしなくてはいけません。 Animal myAnimal = new Dog(); ((Dog)myAnimal).run((long)5);
お礼
回答ありがとうございます。 >子オブジェクトを親オブジェクトへ代入した瞬間に親オブジェクトとして>の振る舞いをするようになります。 インスタンスメソッドの場合、変数の型ではなくオブジェクトの型 でクラスを見にいくと思っていたのですが、変数の型で見に行くのですか? (見当違いな質問ならすいません)
- ngsvx
- ベストアンサー率49% (157/315)
#1です。 代入先の型がスーパークラスなので、 #3さんのおっしゃる通り、longを引数にすると コンパイルエラーになりますね。 失礼しました。 Animal myAnimal = new Dog(); が Dog myAnimal = new Dog() ならrun((long)5);が通りますね。
お礼
回答ありがとうございます。 >longを引数にするとコンパイルエラーになりますね。 Animalクラスにないメソッドだからコンパイルエラーになるのでしょうか? そもそも Animal myAnimal = new Dog(); が良くわかっていないようです。 インスタンスメソッド、インスタンス変数で見にいくクラスが違うのですよね(それがわかっていないようです(泣))
- PED02744
- ベストアンサー率40% (157/390)
ANo.3です。 追伸: Animal myAnimal = new Dog(); -----* この行が Dog myAnimal = new Dog(); -----* ならANo.1さんが正解です。 (long)でキャストすると "My dog is running."になりますし、 (long)でキャストしないと"My animal is running."になります。
- PED02744
- ベストアンサー率40% (157/390)
>出力結果は My animal is running になりますが、わかりません。 >*行は実際のオブジェクトはDog型で,次のmyAnimal.run(5)は >インスタンスメソッドなので、オブジェクトのDogを見に行くと >思うのですが、違うのですか? いいえ。違います。 子オブジェクトを親オブジェクトへ代入した瞬間に親オブジェクトとしての振る舞いをするようになります。 myAnimal自体はAnimalのインスタンスとして振舞いますので、 [my animal is running.] となります。 ANo.1さんはオーバーライドの話をされていますが、(long)でキャストすると、今回の場合は 「メソッド run は引数 long に適用できない」(正しいメッセージ忘れた。まぁ、試せばいいんだけなんだけども(笑)) というコンパイルエラーになるはずです。
- phoenix343
- ベストアンサー率15% (296/1946)
オーバーロード http://www.nextindex.net/java/overload.html Animalクラスから派生したのがDogクラスですね なのでAnimalで宣言した関数はprotected/publicであれば 子であるDogクラスでも使えます。 だからあなたの考え通りでいいと思います。
お礼
回答ありがとうございます URL見に行きます
- ngsvx
- ベストアンサー率49% (157/315)
Animalクラスのrunメソッドの引数はint型。 Dog クラスのはlong型。 そのため、オーバーライド(上書き)されず別なメソッドとして解釈されているためです。 呼び出すときに、 myAnimal.run((long)5); とすれば「My dog is running」が表示されるはずです。
お礼
回答ありがとうございます。 また質問です。 >オーバーライド(上書き)されず別なメソッドとして解釈されているため Dog クラスに妥当なメソッドが無くて継承関係にあるからAnimalクラス を探しにいったのですか?
お礼
補足回答ありがとうございます。 わかりやい説明で初心者な私でも理解できました。