Доступ к полю внешнего класса

Как получить доступ к полю внешнего класса по ссылке на объект внутреннего класса?

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 и многие другие варианты. Есть ли синтаксис, который делает то, что я хочу?


person fredoverflow    schedule 30.06.2011    source источник
comment
Разве цель внутреннего класса не должна использоваться только внутри его внешнего класса?   -  person Heisenbug    schedule 30.06.2011
comment
Я думаю, что это способ сделать это. Если вы чувствуете, что это неправильно, может быть, вы можете подумать о рефакторинге или создании этих классов по-другому?   -  person Luciano    schedule 30.06.2011
comment
Я не знаю другого способа сделать это, но я скажу, что если вам приходится делать такие искривления, это обычно означает, что вам следует переосмыслить дизайн.   -  person Mike Deck    schedule 30.06.2011
comment
@Overbose — миру передается множество экземпляров внутреннего класса. Например, многие классы Iterator являются внутренними классами своих коллекций Iterable. Внутренние классы помогают уменьшить беспорядок в пространстве имен (например, Float, Arc2D.Float, CubicCurve2D.Float, DataBuffer.Float и т. д.).   -  person Ted Hopp    schedule 30.06.2011


Ответы (3)


Есть два способа взглянуть на то, что вы делаете, как на статический метод или как на нестатический метод.

На первый взгляд ваш пример больше похож на статический метод, поскольку он манипулирует состоянием параметра, а не своим собственным состоянием. Статическая проблема была рассмотрена ранее, например. см. Как в Java получить доступ к внешнему классу, если я не во внутреннем классе?

Но ваш пример относится к нестатическому методу, и я думаю, что понимаю, что вы получаете, и почему вы считаете, что внешняя ссылка должна быть возможна. В конце концов, есть и другие ситуации, в которых вы можете получить доступ к деталям реализации других экземпляров вашего собственного типа — например, при переопределении равенства обычно ссылаются на закрытые поля-члены входного параметра. К сожалению, я просто не думаю, что java предоставляет способ ссылаться на другой лексически охватывающий экземпляр. Вероятно, это как-то связано с способом, которым java на самом деле реализует нестатические внутренние классы. Java использует this$0 для своих целей, но у вас нет доступа к этому синтетическому полю.

person jtoberon    schedule 30.06.2011

Как насчет этого решения:

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; 
        }
    }
}
person user1504714    schedule 13.08.2012
comment
Я всегда так делаю, хотя для вашего примера я бы выбрал не примитивное поле. Сохранение только ссылки на родительскую область и доступ к полям через нее позволяет избежать использования устаревшей ссылки для field, когда это объект, а не примитив, что является ключевым преимуществом этого подхода. - person KomodoDave; 16.04.2013

Находясь вне внутреннего класса, я считаю, что при наличии ссылки на экземпляр внутреннего класса невозможно ссылаться на члены экземпляра внешнего класса. Изнутри нестатического внутреннего класса вы, конечно, можете ссылаться на них, используя синтаксис Outer.this.*.

Подумайте об этом так: внутренний класс на самом деле является совершенно отдельным классом. У него есть поле, сгенерированное компилятором (обычно называемое чем-то странным, например this$0). Во внутреннем классе язык позволяет ссылаться на это поле, используя Outer.this; однако этот синтаксический сахар недоступен за пределами самого внутреннего класса. Поле, созданное компилятором, также не является.

person Ted Hopp    schedule 30.06.2011