質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

2419閲覧

オーバーライドしたメソッドのふるまいでわからないことがある。

chankane

総合スコア139

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

2クリップ

投稿2017/06/11 00:36

編集2017/06/11 00:53

###前提・実現したいこと
こんにちは毎度お世話になっております。おそらくかなり初歩的なことでつまずいています。

  1. なぜそのような動作をしているか
  2. 期待通りの表示にするには

以上の2点を教えて頂きたいです。ご教授のほど、よろしくお願いします。
一応探しましたが、過去に同じ質問があったら申し訳ありません。

###発生している問題・エラーメッセージ
ソースのあれれ?とコメントをしたところで、本当は
i am super
と出てほしいのです。

###該当のソースコード

java

1class Super{ 2 void callName(){ 3 System.out.println("i am super"); 4 } 5 6 void callSuperName(){ 7 callName(); 8 } 9} 10 11class Child extends Super{ 12 @Override 13 void callName(){ 14 System.out.println("i am child"); 15 } 16 17 @Override 18 void callSuperName(){ 19 super.callSuperName(); 20 } 21 22 public static void main(String[] args){ 23 Super s = new Super(); 24 Child c = new Child(); 25 26 s.callName();// 期待通り 27 c.callName();// 期待通り 28 29 s.callSuperName();// 期待通り 30 c.callSuperName();// あれれ? 31 } 32}

###出力結果
i am super
i am child
i am super
i am child

chida3👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

こんにちは。回答いたします。

1. なぜそのような動作をしているか
c.callSuperName()コールでは、確かに Super#callSuperName()が実行されます。
Super#callSuperName()に実装されている「callName();」の行は
「this.callName();」に読み替えることができます。
今回のケースでは、thisは「Child c」を表していますので、結果として
Child#callName() が実行されることになります。

2. 期待通りの表示にするには
こちらは、すみません、調査後改めて回答致します。

投稿2017/06/11 01:40

konnok1

総合スコア60

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chankane

2017/06/11 01:50

感覚的につかみづらいですが、 this = c(Childクラスのインスタンス) みたいな感じでしょうか?
konnok1

2017/06/11 02:52

そのご認識で合っています。
konnok1

2017/06/11 02:52

2.の回答例として、Child#callSuperName()の実装を  System.out.println("i am " + super.getClass().getSimpleName()); とする案も考えてみましたが、意に反して出力が  i am Child となってしまいました。
chankane

2017/06/11 03:19

そうですか...。難しいものです。 解決策に関しては、sobue様の回答を参考にさせていただきます。 ご回答ありがとうございました。
guest

0

インスタンスメソッドは、そのインスタンスがどのクラスのインスタンスであるかに依存します。
親クラスの型の変数に代入されていようと、superで親クラスからアクセスされようと、
ChildクラスのインスタンスであるcのcallName()を呼び出した場合、ChildクラスのcallName()が起動します。
いうなれば、継承の中で最後にオーバーライドされたメソッドが起動することになります。
つまり、cに対してcallSuperName()した場合、
0. SuperクラスのcallSuperName()が呼ばれる
0. SuperクラスからcallName()が呼ばれ、cの実体型ChildクラスのcallName()が起動する

という流れになり、"i am child"と出力されるのです。

では、どうすればいいかという話ですが、ChildクラスのcallSuperName()で、super.callName()すればいいです。

投稿2017/06/11 01:33

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chankane

2017/06/11 01:54

感覚的につかみづらいですが、インスタンスがChildだからだよと思うしかないのでしょうか? どうすればいいかについては少し色々な人の提案を試させてください。
swordone

2017/06/11 01:58

そうです。メソッドがオーバーライドされた場合、オーバーライドされる前のメソッドが見えなくなるので、Childクラスで定義されたメソッドが起動されることになります。
chankane

2017/06/11 02:15

親クラス側からの呼び出しでも「見えなくなる」という効果が働いているのですね。そこの疑問は解決です(*^^)v 余談ですが、privateでない親クラスのメソッドを親クラス自身の別のメソッドから呼び出す。という構造はよくない感じですか?正直動作が想定外すぎてこれだと困ります。
swordone

2017/06/11 02:56

sobueさんの回答が適していると思います
chankane

2017/06/11 03:20

今回はそれで解決いたしました。ありがとうございました<(_ _)>
guest

0

ベストアンサー

superクラスのcallSuperName()を呼んで、superクラスのcallName()を呼んでいるのですが
ChildクラスのインスタンスなのでOverrideが働きChildクラスのcallName()が呼び出されます。

java

1package test1; 2 3 public class Super{ 4 5 String str = "i am super"; 6 void callName(){ 7 System.out.println(str); 8 } 9 10 void callSuperName(){ 11 callName(); 12 } 13 14 public static void main(String[] args){ 15 Super s = new Super(); 16 Child c = new Child(); 17 18 s.callName();// 期待通り 19 c.callName();// 期待通り 20 21 s.callSuperName();// 期待通り 22 c.callSuperName();// あれれ? 23 } 24} 25

java

1package test1; 2 3public class Child extends Super { 4 5 String str = "i am child"; 6 7 @Override 8 void callName() { 9 10 System.out.println(str); 11 12 } 13 14 // @Override 15 void callSuperName() { 16 System.out.println(super.str); 17 } 18}

解決策としては上記があると思います。

投稿2017/06/11 01:36

sobue

総合スコア329

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sobue

2017/06/11 01:43

sword oneさんが先に回答されてますね。僕の提案は冗長なコードがあるので参考程度にしてください。 結果は希望通りになるのは確認済みです。
chankane

2017/06/11 01:52

メンバはprivateで統一したいです。少し色々と試させてください。 ご回答ありがとうございます。
chankane

2017/06/11 03:17

いろいろと試してました。 ご回答の案で解決いたいしました。ありがとうございます。 最後にひとつだけ。今回はこれで解決なのですが、callSuperName()がコンストラクタだった場合にはどう回避すればよいでしょうか?教えてください<(_ _)>
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問