Нарушение инкапсуляции и сокрытие информации в Java

Рассмотрим следующий фрагмент.

package breakoop;

public class BreakOOP {

    public static class A{
        private int a;
    }

    public static class B extends A{
        public int f(){
            return super.a;
        }
    }

    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.f());
    }
}

Пример компилируется, только если A и B инкапсулированы в класс BreakOOP.

Кажется, это противоречит некоторым фундаментальным концепциям ООП. Может кто-нибудь объяснить, почему это компилируется? Какова причина этого?


person Igor Ševo    schedule 27.09.2016    source источник
comment
Вы имеете в виду super.a, я думаю. Это компилируется, потому что в спецификации указано, что любой закрытый член виден внутри области класса верхнего уровня, то есть в вашем случае в пределах BreakOOP (мне нужно будет найти соответствующий раздел JLS).   -  person Thomas    schedule 27.09.2016
comment
Внутренние классы получают правила видимости от своих родительских классов. Почему это? - Можно обсудить, это именно то, как это происходит в Java. Таким образом, доступ к super.a из B подобен двум приватным переменным в классе BreakOOP. Если вам нужна более обширная защита, вам придется переместить их в разные единицы компиляции.   -  person mtj    schedule 27.09.2016
comment
Я не знаю, почему это разрешено, но аргумент о том, что это увеличивает инкапсуляцию, по моему мнению, похож на аргумент о том, почему ключевое слово friend в C++ может увеличить инкапсуляцию.   -  person jmrah    schedule 27.09.2016
comment
Почему вы думаете, что он не должен компилироваться?   -  person fgb    schedule 27.09.2016


Ответы (2)


Проверьте это: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html. В нем говорится, что он увеличивает инкапсуляцию, позволяя классу static получать доступ к закрытым членам класса верхнего уровня (иногда вам может понадобиться это сделать). И a является закрытым членом класса A, который находится в области действия BreakOOP, что, в свою очередь, делает его доступным внутри класса B .

person uoyilmaz    schedule 27.09.2016

В спецификации языка Java говорится:

Член закрытого класса или конструктор доступен только внутри тела класса верхнего уровня (§7.6), которое заключает в себе объявление члена или конструктора.

Поскольку классы A и B определены в теле BreakOOP, применяется это правило, и B может видеть закрытые члены A.

Что касается концепций ООП: поскольку A и B являются статическими внутренними классами, у них нет особой связи жизненного цикла с BreakOOP, которая есть у настоящих внутренних классов (т.е. вам не нужен экземпляр BreakOOP для создания нового экземпляра A или B, но у них все еще есть несколько особые отношения в том, что у них есть доступ к закрытым членам.Если у них не должно быть такого рода отношений, то они должны быть не внутренними классами, а настоящими классами верхнего уровня.

person Thomas    schedule 27.09.2016