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 publique en Java si elle ne peut toujours pas être accessible en dehors de la classe contenant? Ou peut-il?
public class DataStructure {
// ...
private class InnerEvenIterator {
// ...
public boolean hasNext() { // Why public?
// ...
}
}
}
6 réponses
Si la classe InnerEvenIterator
n'étend aucune classe ou n'implémente aucune interface, je pense que c'est un non-sens car aucune autre classe ne peut y accéder.
Cependant, s'il étend ou implémente une 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;
}
}
Cette méthode peut être faite public
afin d'indiquer qu'elle est sémantiquement publique, malgré le fait que le compilateur n'applique pas les règles de visibilité dans ce cas particulier.
Imaginez que lors d'un refactoring, vous devez faire de cette classe interne un niveau supérieur. Si cette méthode est private
, Comment décideriez-vous si elle devrait être faite public
, ou si un modificateur plus restrictif devrait être utilisé? Déclarer la méthode comme public
indique au lecteur les intentions de l'auteur original - cette méthode ne devrait pas être considéré comme un détail de mise en œuvre.
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
}
}
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 elle ne compilera pas.
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'elles sont en fait protected
Si la classe interne est privée, elle ne peut pas être accessible par 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 structure de données de classe, ceci est complètement équivalent à:
public class DataStructure {
// ...
private class InnerEvenIterator {
// ...
private boolean hasNext() {
// ...
}
}
}
C'est parce que seule DataStructure peut y accéder, donc peu importe si vous le définissez sur public ou privé. De toute façon, DataStructure est toujours la seule classe qui peut y accéder. Utilisez n'importe quel modificateur que vous aimez, cela ne fait aucune différence fonctionnelle. La seule fois 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 changer en public. Certes, aucun ne fait réellement de différence.
Si vous prévoyez d'utiliser une classe interne dans d'autres classes, et donc 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 commun pour eux de le faire, mais ce n'est certainement pas nécessaire.