2012-10-23 16 views
8

内部クラスが存在するときに継承がJavaでどのように機能するかを理解できません。私は現在、子クラスがその親クラスの内部クラスの機能を少し変更する必要がある何かに取り組んでいます。私は以下の簡単な、同類の例を思いついた。内部クラスが関与するときにJava継承がどのように機能するか

私はこのコードで "私はChildClass.InnerClassです"と表示する代わりに、 "私はParentClass.InnerClassです"と表示します。どうしてこれなの?また、メイン のobjオブジェクトをChildClass型に変更すると、出力は "私はChildClass.InnerClassです"に変わります。どうしてこれなの?

一般に、オブジェクトの親クラスの内部オブジェクトの動作を変更するには、どのような方法が推奨されますか?

class InnerClassTest { 
    //----------------------------------------------------------------------- 
    // PARENT CLASS 
    class ParentClass { 
     public ParentClass() { 
     x = new InnerClass(); 
     } 

     InnerClass x; 

     class InnerClass { 
     public void speak() { 
      System.out.println("I am a ParentClass.InnerClass"); 
     } 
     } 
    } 

    //----------------------------------------------------------------------- 
    // CHILD CLASS 
    class ChildClass extends ParentClass { 
     public ChildClass() { 
     x = new InnerClass(); 
     } 

     InnerClass x; 

     class InnerClass extends ParentClass.InnerClass { 
     public void speak() { 
      System.out.println("I am a ChildClass.InnerClass"); 
     } 
     } 
    } 

    //----------------------------------------------------------------------- 
    // MAIN 
    public static void main(String[] args) { 
     ParentClass obj = (new InnerClassTest()).new ChildClass(); 
     obj.x.speak(); 
    } 
} 

答えて

6

変数はメソッドとして "オーバーライド"されません。

xChildであると予想していましたが、xは変数でありメソッドではないためではありません。

しかし、注意を払う:あなたの参照型はparentClassの背後にある本当のインスタンスがChildClassであってもParentClassInnerClass属性にParentClassそうobj.xポイントです!あなたの予想文を表示するためには、あなたがChildClassへの型参照に変更する必要が

:より良い概念を理解するために

public static void main(String[] args) { 
     ChildClass obj = (new InnerClassTest()).new ChildClass(); 
     obj.x.speak(); 
} 

を、両方ParentClassChildClassクラスでメソッドを定義してみてください

public InnerClass getInnerClass(){ 
    return x; 
} 

とし、xをプライベートにします。

"オーバーライドコンセプト"が適用されます。

あなたの最後の呼び出しは、この場合には、次のようになります。

ParentClass obj = (new InnerClassTest()).new ChildClass(); 
obj.getInnerClass().speak(); 

内部クラスの動作を変更するには、テンプレート法パターン以上を考える:Strategyパターン(DIPのため、より尊重)

3

InnerClass x; 

FR再宣言を削除しますom子クラス。したがって、あなたはxの1つしか持たず、子クラスのコンストラクタで再割り当てされます。これは、1つを意味しますx(子ctorで作成されたオブジェクトを参照してください)。

親クラスには隠れています。 2つのフィールドを持ち、2つの異なるオブジェクトを参照することになります。そして、静(コンパイル時または初期の)変数の場合には結合、一般的には

ParentClass obj; 
//obj.x means the x in parent 

ChildClass obj; 
//obj.x means the x in child 
+0

'ParentClass obj; //obj.xはchild'のxを意味します??あなたはChildClass objを意味しましたか? – exexzian

+0

@sansix:そうです。編集していただきありがとうございます。ソリューションの場合は –

+0

+1 – exexzian

1

に、 オブジェクトの挙動を変更する方法をお勧めは何ですか親クラスの内部オブジェクト?

まず、あまり複雑でないデザインを使用することをおすすめします。子クラスはそのメソッドをオーバーライドすることによって親の動作を変更する必要がありますので、この依存関係の作成をオーバーライドしてクラス階層の最上部でこのオブジェクトを管理するファクトリメソッドnewInnerClass()を追加するだけです。

newInnerClass()は、適切なインターフェイスを持つ限り、定義されたクラスをインスタンス化できるため、これはあなたの提案よりも柔軟性があります。

関連する問題