2011-06-30 19 views
7

内部クラスのオブジェクトへの参照がある場合、外部クラスのフィールドにアクセスするにはどうすればよいですか?外部クラスのフィールドへのアクセス

class Outer 
{ 
    int field; 

    class Inner 
    { 
     void method(Inner parameter) 
     { 
      // working on the current instance is easy :) 
      field = 0; 
      Outer.this.field = 1; 

      // working on another instance is hard :(
      parameter.field = 2;    // does not compile 
      parameter.Outer.this.field = 3; // does not compile 
      parameter.outer().field = 4;  // This works... 
     } 

     // ...but I really don't want to have to write this method! 
     Outer outer() 
     { 
      return Outer.this; 
     } 
    } 
} 

また、私はOuter.parameter.fieldと他の多くの変形を試しました。私がしたいことをする構文がありますか?

+0

はちょうどその外側のクラス内で使用されてする内部クラスの目的ではないのですか? – Heisenbug

+0

私はそうする方法だと思います。もしそれが間違っていると感じたら、あなたはリファクタリングを考えたり、それらのクラスを異なる方法で構築したりすることができますか? – Luciano

+5

それ以外の方法はわかりませんが、そのような曲げをする必要がある場合は、通常、デザインを再考する必要があると言います。 –

答えて

2

あなたがやっていることを、静的メソッドとして、または非静的メソッドとして見るには、2通りの方法があります。

一見すると、自分の状態ではなくパラメータの状態を操作しているので、あなたの例は静的メソッドのように見えます。静的な問題は、以前にカバーされていた。 In Java, how do I access the outer class when I'm not in the inner class?

あなたの例は非静的な方法ですが、私はあなたが何を得ているのか、なぜ外部参照が可能であるべきだと思うのかを見ています。結局のところ、あなた自身の型の他のインスタンスの実装の詳細にアクセスできる他の状況があります。たとえば、equalsをオーバーライドするときに入力パラメータのプライベートメンバーフィールドを参照するのが一般的です。残念ながら、私はjavaが他のレキシカルに囲まれたインスタンスを参照する方法を提供しているとは思わない。これはおそらくthe way that java actually implements non-static inner classesと関係があります。 Javaはthis$0を独自の目的で使用しますが、この合成フィールドにはアクセスできません。

8

内部クラスの外側からは、内部クラスインスタンスへの参照を渡して、外部クラスインスタンスのメンバーを参照する方法はないと私は信じています。静的でない内部クラスの内部からは、Outer.this.*構文を使用してそれらを参照できます。

このように考えると、内部クラスは実際は完全に別のクラスです。それはコンパイラ生成のフィールドを持っています(普通this$0のような変わった名前です)。内部クラス内では、言語を使用すると、Outer.thisを使用してそのフィールドを参照できます。しかし、構文上の砂糖は、内部クラスそのものの外では利用できません。どちらもコンパイラ生成フィールドではありません。

8

どのようにこのソリューションについて:

class Outer 
{ 
    int field; 

    class Inner 
    { 
     final Outer outer = Outer.this; 
     void method(Inner parameter) 
     { 
      // working on the current instance is easy :) 
      field = 0; 
      Outer.this.field = 1; 

      // working on another instance: 
      parameter.outer.field = 2; 
     } 
    } 
} 
+0

これは私がいつもそれをする方法ですが、あなたの例のための最初のフィールド。親スコープへの参照のみを格納し、それを介してフィールドにアクセスすることは、このアプローチの主な利点である、プリミティブではなくObjectであるときに 'field'に対する古い参照を使用することを避けます。 – KomodoDave

関連する問題