Зачем делать закрытый член внутреннего класса публичным в Java? - PullRequest
31 голосов
/ 07 июня 2011

В чем причина объявления члена закрытого внутреннего класса общедоступным в Java, если к нему по-прежнему нельзя получить доступ за пределами содержащего класса?Или это может?

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }
}

Ответы [ 6 ]

32 голосов
/ 07 июня 2011

Если класс InnerEvenIterator не расширяет какой-либо класс или не реализует какой-либо интерфейс, я думаю, что это чепуха, потому что никакой другой класс не может получить доступ к любому его экземпляру.

Однако, если он расширяет или реализует любой другой не приватный класс или интерфейс, это имеет смысл. Пример:

interface EvenIterator {
    public boolean hasNext();
}


public class DataStructure {
    // ...

    private class InnerEvenIterator implements EvenIterator{
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }

    InnerEvenIterator iterator;

    public EvenIterator getIterator(){
         return iterator;
    }     

}
14 голосов
/ 07 июня 2011

Этот метод можно сделать public, чтобы указать, что он семантически общедоступен, несмотря на тот факт, что компилятор не применяет правила видимости в данном конкретном случае.

Представьте, что во время рефакторинга вам нужно сделать этот внутренний класс на высшем уровне. Если этот метод private, как вы решите, должен ли он быть сделан public, или следует использовать какой-то более ограничительный модификатор? Объявление метода как public сообщает читателю о намерениях первоначального автора - этот метод не должен рассматриваться как деталь реализации.

8 голосов
/ 07 июня 2011

Это полезно при реализации любых interface.

class DataStructure implements Iterable<DataStructure> {

    @Override
    public Iterator<DataStructure> iterator() {
        return new InnerEvenIterator();
    }
    // ...        

    private class InnerEvenIterator implements Iterator<DataStructure> {
        // ...    
        public boolean hasNext() { // Why public?
            // ...
            return false;
        }

        @Override
        public DataStructure next() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    public static void main(String[] ex) {
        DataStructure ds = new DataStructure();
        Iterator<DataStructure> ids = ds.iterator();
        ids.hasNext(); // accessable            
    }
}
4 голосов
/ 07 июня 2011

Я думаю, вам не хватает реализации интерфейсной части Iterator в вашем примере кода.В этом случае вы не можете заставить метод hasNext() иметь любой другой идентификатор видимости, кроме public, так как это приведет к снижению его видимости (методы интерфейса имеют общедоступную видимость) и не будет компилироваться.

3 голосов
/ 07 июня 2011

Существует множество комбинаций модификаторов доступа, которые бесполезны.Открытый метод в закрытом внутреннем классе полезен, только если он реализует открытый метод в открытом классе / интерфейсе.

public class DataStructure {
    // ...

    private class InnerEvenIterator implements Iterator {
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }

    public Iterator iterator() {
        return new InnerEvenIterator();
    }
}

Кстати: абстрактные классы часто имеют конструкторы public, когда на самом деле они protected

1 голос
/ 11 января 2013

Если внутренний класс является закрытым, к нему нельзя получить доступ по имени вне внешнего класса. Внутренние и внешние классы имеют доступ к закрытым методам друг друга и частным переменным экземпляра. Пока вы находитесь внутри внутреннего или внешнего класса, модификаторы public и private имеют одинаковый эффект. В вашем примере кода:

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

        public boolean hasNext() { // Why public?
            // ...
        }
    }
}

Что касается класса DataStructure, это полностью эквивалентно:

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

        private boolean hasNext() {
            // ...
        }
    }
}

Это потому, что только DataStructure может получить к нему доступ, поэтому не имеет значения, если вы установите его как открытый или закрытый. В любом случае, DataStructure остается единственным классом, который может получить к нему доступ. Используйте любой модификатор, который вам нравится, он не имеет никакой функциональной разницы. Единственный случай, когда вы не можете выбирать случайным образом, - это когда вы внедряете или расширяете, и в этом случае вы не можете уменьшить доступ, но можете его увеличить. Так что если у абстрактного метода есть защищенный доступ, вы можете изменить его на публичный. Конечно, никто не имеет никакого значения.

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

Кроме того, я не вижу никаких требований для внутренних классов, расширяющих или реализующих другие классы. Для них это может быть обычным делом, но это определенно не обязательно.

...