Внутренние классы с именами методов и другими сигнатурами, чем внешний класс - PullRequest
9 голосов
/ 29 сентября 2011

Я знаю, как заставить этот код работать, но мне любопытно, почему компилятор не может понять, что это вызов метода внешнего класса:

public class Example {
    public void doSomething(int a, int b)
    {
    }

    public class Request
    {
        public int a;
        public int b;

        public void doSomething()
        {
            doSomething(a,b); // Error. Fix: Example.this.doSomething(a,b);
        }
    }
}

Есть ли более глубокийНеужели для этого нужна защита, чем защита кодеров от ошибок?

Ответы [ 3 ]

8 голосов
/ 29 сентября 2011

По определению языка метод внешнего класса не виден во внутреннем классе, поскольку он затенен .

Затенение основано на имени, а не на подписи. Это хорошая вещь.

Рассмотрим альтернативу. Вы можете скрыть подмножество перегрузок методов. Кто-то может попытаться изменить аргументы в вызове, чтобы вызвать один из других перегруженных методов. Простое изменение аргументов может привести к изменению объекта получателя. Это было бы удивительно и могло бы стоить времени на отладку.

Из спецификации языка Java, 6.3.1:

Некоторые объявления могут быть скрыты в части их области действия другими объявление того же имени, в этом случае простое имя не может быть используется для ссылки на объявленную сущность. Объявление d типа с именем n скрывает объявления любых других типов с именем n, которые находятся в область действия в точке, где d встречается во всей области действия области d.

...

Объявление d называется видимым в точке p программы, если область действия d включает в себя p, и d не скрывается никаким другим объявлением в п. Когда обсуждаемый программный пункт ясен из контекста, мы часто будем просто говорить, что декларация видима.

1 голос
/ 29 сентября 2011

Это будет работать:

public class Example {
    public void doSomething(final int a, final int b) {
    }

    public class Request {
        public int a;
        public int b;

        public void foo() {
            doSomething(a, b); // Error. Fix: Example.this.doSomething(a,b);
        }
    }
}

У вас есть столкновение пространства имен в имени функции doSomething, следовательно, необходимо указать.

0 голосов
/ 29 сентября 2011

Внутренние классы по умолчанию не наследуются от своего соответствующего внешнего класса.

...