2017-08-02 10 views
2

私はprintThreadを呼び出すと、なぜ0と3を印刷していますか?子クラスメソッドの出力は印刷されませんか?

class Super { 

    Super() { 
     three(); 
    } 

    void three() { 
     System.out.println("three"); 
    } 
} 

class Child extends Super { 
    int three = (int) Math.PI; // That is, 3 

    void three() { 
     System.out.println(three); 
    } 

    public static void main(String[] args) { 
     Child t = new Child(); 
     t.three(); 
    } 
} 

出力に含まは0と3 ですが、それは(Superであなたの実装が呼び出されることはありません)あなたはこのをステップ実行した場合、three()は必ず子クラスのメソッドになります3,3

+0

これはどの言語ですか?あなたのコードスニペットはコンパイルされるべきではありません – Lino

+0

あなたは本当のコードを提供する必要があります。 – csmckelvey

+0

私はちょうどコード – shiv

答えて

1

あなたが最初newで、その後new SomeType(..)を呼び出す(intのために、それはオブジェクト参照nullため、booleanfalseため、0です)そのdefault valuesまで設定フィールドでSomeTypeクラスのインスタンスを作成します。

オブジェクトの適切な初期化は、コンストラクタコードによって後で実行されます。このため、フィールドを初期化する責任を負うコードは、各コンストラクターの開始時に移動されます(サブクラスのコードはしばしばsupperクラスの設定に依存するため、super()呼び出し後に移動されます)。だから、

class Child extends Super { 
    int three = (int) Math.PI; // That is, 3 

class Child extends Super { 
    int three = 0;//initialization to proper value is moved to constructors 
        //         | 
    Child(){  //         | 
     super(); //         | 
     three = (int) Math.PI; //<--------------------+ 
    } 
    ... 
} 

としてコンパイルされsuper()threeフィールドを適切に初期化する前に呼び出されているので、その値がまだ0に設定されています。

スーパークラスのコンストラクタはthree();メソッドを呼び出しますが、polymorphismのためにChildクラスでオーバーライドされているため、コードChild#threeが呼び出されます。そのコードはthreeの印刷値であり、適切な初期化はまだ行われていないため、最初にデフォルト値0newオペレータによって設定されます)が表示されています。

three();からt.three();までコンストラクタを終了した後で、その時点でthree3(結果は(int) Math.PI;)に正しく初期化されており、3と表示されています。


このような問題を回避するには、サブクラスでオーバーライドできるコンストラクタメソッドを使用しないでください。フィールドを直接使用するか、private、final、またはstaticメソッドを使用します。

+0

このケースはインターフェイスに従っていますか?私たちはインターフェイスがコンストラクタを持っていないことを知っています。 – shiv

+0

@shiv "インターフェイスにはconstuctorがありません"という真実がありますが、*インターフェイスをインスタンス化できないことも忘れないでください。非抽象クラスのみをインスタンス化することができるので、インターフェイスに関してどのような問題があるかわかりません。 – Pshemo

+0

@shivもしあなたが疑問を記述している場所については、新たに別のフォローアップ質問をすることができます。 – Pshemo

0

でなければなりません。

また、Super()three()への最初の呼び出しは、実際に最初の呼び出しが0(子オブジェクトがまだ完全に初期化されていない)であることを理由故に、Childのコンストラクタの残りの部分の前に実行されます。

関連する問題