web-dev-qa-db-fra.com

Pourquoi rendre public un membre de classe interne privé en Java?

Quelle est la raison de déclarer un membre d'une classe interne privée public dans Java s'il n'est toujours pas accessible en dehors de la classe contenante? Ou est-ce possible?

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

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

Si la classe InnerEvenIterator n'étend aucune classe ni n'implémente aucune interface, je pense que c'est absurde car aucune autre classe ne peut y accéder.

Cependant, s'il étend ou implémente toute autre classe ou interface non privée, cela a du sens. Un exemple:

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;
    }     

}
32
Gursel Koca

Cette méthode peut être rendue public afin d'indiquer qu'elle est sémantiquement publique, malgré le fait que le compilateur n'applique pas de règles de visibilité dans ce cas particulier.

Imaginez que lors d'une refactorisation, vous devez faire de cette classe interne un niveau supérieur. Si cette méthode est private, comment décideriez-vous si elle doit être faite public, ou si un modificateur plus restrictif doit être utilisé? Déclarer la méthode comme public indique au lecteur les intentions de l'auteur original - cette méthode ne doit pas être considérée comme un détail d'implémentation.

14
axtavt

Il est utile lorsque vous implémentez un 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            
    }
}
8

Je pense qu'il vous manque l'implémentation de la partie d'interface Iterator dans votre exemple de code. Dans ce cas, vous ne pouvez pas faire en sorte que la méthode hasNext() ait un autre identifiant de visibilité autre que public car cela finirait par réduire sa visibilité (les méthodes d'interface ont une visibilité publique) et ne compilera pas.

4
Sanjay T. Sharma

Il existe de nombreuses combinaisons de modificateurs d'accès qui ne sont pas utiles. Une méthode publique dans une classe interne privée n'est utile que si elle implémente une méthode publique dans une classe/interface publique.

public class DataStructure {
    // ...

    private class InnerEvenIterator implements Iterator {
        // ...

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

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

BTW: les classes abstraites ont souvent des constructeurs public alors qu'en réalité elles sont protected

3
Peter Lawrey

Si la classe interne est privée, elle n'est pas accessible par son nom en dehors de la classe externe. Les classes internes et externes ont accès aux méthodes privées et aux variables d'instance privées de l'autre. Tant que vous êtes dans la classe interne ou externe, les modificateurs public et private ont le même effet. Dans votre exemple de code:

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

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

En ce qui concerne la classe DataStructure, cela équivaut à:

public class DataStructure {
    // ...

    private class InnerEvenIterator {
        // ...

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

En effet, seul DataStructure peut y accéder, donc peu importe si vous le définissez sur public ou privé. Quoi qu'il en soit, DataStructure est toujours la seule classe qui peut y accéder. Utilisez le modificateur que vous aimez, cela ne fait aucune différence fonctionnelle. Le seul moment où vous ne pouvez pas choisir au hasard est lorsque vous implémentez ou étendez, auquel cas vous ne pouvez pas réduire l'accès, mais vous pouvez l'augmenter. Donc, si une méthode abstraite a un accès protégé, vous pouvez la modifier en public. Certes, ni l'un ni l'autre ne fait vraiment de différence.

Si vous prévoyez d'utiliser une classe interne dans d'autres classes, et donc de la rendre publique, vous ne devriez probablement pas en faire une classe interne en premier lieu.

De plus, je ne vois aucune exigence pour les classes internes étendant ou implémentant d'autres classes. Il pourrait être courant pour eux de le faire, mais ce n'est certainement pas obligatoire.

1
sage88