14

内部クラスが存在する場合、Javaで継承がどのように機能するかを理解するのに問題があります。私は現在、子クラスがその親の内部クラスの機能をわずかに変更する必要がある何かに取り組んでいます。以下に、より単純で類似した例を考え出しました。

このコードは「私はChildClass.InnerClassです」と出力することを期待していましたが、代わりに「私はParentClass.InnerClassです」と出力します。どうしてこれなの?また、mainのobjオブジェクトをChildClass型に変更すると、出力は「IamaChildClass.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();
   }
}
4

3 に答える 3

9

メソッドのように変数が「オーバーライド」されることはありません。

あなたの呼び出しでは、あなたは'sであると期待xしていましたが、それは変数であり、メソッドではないためではありません。Childx

ただし、注意してください。実際のインスタンスが!である場合でも、参照型は's属性ParentClassobj.x指します。ParentClassInnerClassparentClassChildClass

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();

内部クラスの動作を変更するには、テンプレートメソッドパターン以上を考えてください。戦略パターン(DIPをより尊重するため)

于 2012-10-23T23:07:22.830 に答える
3

再宣言を削除します

InnerClass x; 

子クラスから。したがって、1つだけがxあり、子クラスのコンストラクターで再割り当てされます。これは1つを意味xします(子ctorで作成されたオブジェクトを参照)。

親クラスにあるものを非表示にしています。これが、2つの異なるオブジェクトを参照する2つのフィールドを持つことになります。また、変数の場合は静的(コンパイル時または早期)バインディングのため、

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

ChildClass obj; 
//obj.x means the x in child
于 2012-10-23T23:11:43.807 に答える
0

一般に、オブジェクトの親クラスの内部オブジェクトの動作を変更するための推奨される方法は何ですか?

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

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

于 2012-10-23T23:31:34.920 に答える