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

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

ただいまの
回答率

87.48%

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 2,089

score 139

前提・実現したいこと

こんにちは毎度お世話になっております。おそらくかなり初歩的なことでつまずいています。

  1. なぜそのような動作をしているか
  2. 期待通りの表示にするには
    以上の2点を教えて頂きたいです。ご教授のほど、よろしくお願いします。
    一応探しましたが、過去に同じ質問があったら申し訳ありません。

発生している問題・エラーメッセージ

ソースのあれれ?とコメントをしたところで、本当は
i am super
と出てほしいのです。

該当のソースコード

class Super{
    void callName(){
        System.out.println("i am super");
    }

    void callSuperName(){
        callName();
    }
}

class Child extends Super{
    @Override
    void callName(){
        System.out.println("i am child");
    }

    @Override
    void callSuperName(){
        super.callSuperName();
    }

    public static void main(String[] args){
        Super s = new Super();
        Child c = new Child();

        s.callName();// 期待通り
        c.callName();// 期待通り

        s.callSuperName();// 期待通り
        c.callSuperName();// あれれ?
    }
}

出力結果

i am super
i am child
i am super
i am child

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

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

  1. SuperクラスのcallSuperName()が呼ばれる
  2. SuperクラスからcallName()が呼ばれ、cの実体型ChildクラスのcallName()が起動する

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/11 11:15

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

    キャンセル

  • 2017/06/11 11:56

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

    キャンセル

  • 2017/06/11 12:20

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

    キャンセル

+1

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/11 10:50

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

    キャンセル

  • 2017/06/11 11:52

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

    キャンセル

  • 2017/06/11 11:52

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

    キャンセル

  • 2017/06/11 12:19

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

    キャンセル

checkベストアンサー

0

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

package test1;

 public class Super{

     String str = "i am super";
    void callName(){
        System.out.println(str);
    }

    void callSuperName(){
        callName();
    }

    public static void main(String[] args){
        Super s = new Super();
        Child c = new Child();

        s.callName();// 期待通り
        c.callName();// 期待通り

        s.callSuperName();// 期待通り
        c.callSuperName();// あれれ?
    }
}
package test1;

public class Child extends Super {

    String str = "i am child";

    @Override
    void callName() {

        System.out.println(str);

    }

    // @Override
    void callSuperName() {
        System.out.println(super.str);
    }
}


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/11 10:43

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

    キャンセル

  • 2017/06/11 10:52

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

    キャンセル

  • 2017/06/11 12:17

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

    キャンセル

  • 2017/06/11 14:19

    すみません
    https://www.jpcert.or.jp/java-rules/met05-j.html
    こちらのサイトにそのことについての記載がありました。
    以上、ありがとうございました。ベストアンサーに選ばせていただきます。

    キャンセル

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

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る