2017-01-01 13 views
-1

基本的には、以下のようなコードがあります。実行すると、私は次の出力を期待:オーバーライドされたメソッド内での子インスタンス変数の変更

Parent doing work 
Child overriding. variable=5 
Child overriding. variable=10 
Child childMethod(). variable=10 

Parent doing work 
Child2 overriding. variable=5 
Child2 overriding. variable=10 
Child2 childMethod(). variable=10 

は、私は何を取得すると、次の出力です:それが宣言され、「前」variableが使用されることを、この不一致のため

Parent doing work 
Child overriding. variable=0 
Child overriding. variable=10 
Child childMethod(). variable=5 

Parent doing work 
Child2 overriding. variable=0 
Child2 overriding. variable=10 
Child2 childMethod(). variable=10 

私の理論があります。これは

  1. variableに基づいて出力(INTデフォルト)クラスChildの場合

  2. に従って0に設定初期値、variableは一見5のその想定初期値を回復有します。

は、それが宣言される「前」variableが使用されることを、この正しいですか?また、これが期待された動作である理由の裏には何らかの理由がありますか?


public static void main(String[] params) { 
    Parent child = new Child(); 
    child.childMethod(); 

    System.out.println(); 

    Parent child2 = new Child2(); 
    child2.childMethod(); 
} 

public static abstract class Parent { 

    public Parent() { 
     method(); 
    } 

    public void method() { 
     System.out.println("Parent doing work"); 
    } 

    abstract void childMethod(); 
} 

public static class Child extends Parent { 
    int variable = 5; 

    @Override 
    public void method() { 
     super.method(); 
     System.out.println("Child overriding. variable=" + variable); 
     variable = 10; 
     System.out.println("Child overriding. variable=" + variable); 
    } 

    public void childMethod() { 
     System.out.println("Child childMethod(). variable=" + variable); 
    } 

} 

public static class Child2 extends Parent { 
    int variable; 

    @Override 
    public void method() { 
     super.method(); 
     System.out.println("Child2 overriding. variable=" + variable); 
     variable = 10; 
     System.out.println("Child2 overriding. variable=" + variable); 
    } 

    public void childMethod() { 
     System.out.println("Child2 childMethod(). variable=" + variable); 
    } 

} 
+0

これは悪いコードデザインです。あなたはそれを説明しようとすべきではなく、ただそれを忘れてはなりません。 – brummfondel

+2

すでに何度も答えられている可能性があります。コンストラクタから仮想メソッドを呼び出す動作について調べましたか? –

+1

オーバーライドされたメソッド 'method'は、変数' variable'が初期化される前に呼び出されます。デバッガを使用して、ステップごとに何が起こるかを確認します。このような状況を回避するには、コンストラクタでfinalメソッドを呼び出すだけです。 –

答えて

4

それは非常に簡単です。子クラスは、親クラスの構築が完了した後にのみ初期化されます。親のコンストラクタ中に子の状態を調べたり変更したりすると、初期化されていないフィールドと対話していることになります。

あなたの場合、デフォルト値の0が読み込まれています。子供が初期化すると、変更は破棄されます。

関連する問題