235 votes

Pourquoi une interface interne statique serait-elle utilisée en Java?

Je viens de trouver une interface interne statique dans notre code-base.

 class Foo {
    public static interface Bar {
        /* snip */
    }
    /* snip */
}
 

Je n'avais jamais vu ça avant. Le développeur d'origine est hors de portée. Par conséquent, je dois demander à SO:

Quelle est la sémantique derrière une interface statique? Qu'est-ce qui changerait si je supprimais le static ? Pourquoi quelqu'un ferait-il cela?

292voto

Jesse Glick Points 3877

Le mot-clé static dans l'exemple ci-dessus est redondante (imbriquée interface est automatiquement "statique") et peut être enlevé sans effet sur la sémantique; je le recommande à être supprimé. Il en va de même pour le "bien public" sur les méthodes d'interface et de "public final" sur l'interface des champs - les modificateurs sont redondantes et juste encombrer le code source.

De toute façon, le développeur est le simple fait de déclarer une interface nommée Foo.Bar. Il n'y a aucune association avec la classe englobante, sauf que le code ne peut pas accéder à Toto ne sera pas en mesure d'accéder à Toto.Bar soit. (À partir du code source - le bytecode ou de réflexion peuvent accéder à Toto.Barre, même si Toto est colis-privé!)

Il est acceptable de style pour créer un imbriquée à l'interface de cette façon, si vous vous attendez à être utilisé uniquement à partir de l'extérieur de la classe, de sorte que vous ne créez pas un nouveau haut-niveau nom. Par exemple:

public class Foo {
    public interface Bar {
        void callback();
    }
    public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
    public void callback() {...}
});

71voto

ColinD Points 48573

La question a été posée, mais une bonne raison d'utiliser un intérieur de l'interface est si sa fonction est directement liée à la classe il est. Un bon exemple de ceci est un Écouteur. Si vous aviez une classe Foo et que vous vouliez que les autres classes puissent être en mesure d'écouter les événements sur elle, vous pouvez déclarer une interface nommée FooListener, qui est ok, mais il serait sans doute plus clair pour déclarer un à l'intérieur de l'interface et ceux d'autres classes implémentent des Foo.À l'écoute (un à l'intérieur de la classe Foo.L'événement n'est pas mauvais avec cette).

14voto

Bas Leijdekkers Points 2656

Les interfaces internes sont implicitement statiques. Le modificateur statique dans votre exemple peut être supprimé sans modifier la sémantique du code. Voir aussi la partie pertinente de la spécification du langage Java

9voto

Clinton R. Nixon Points 4283

Une interface interne doit être statique pour être accessible. L'interface n'est pas associée aux instances de la classe, mais à la classe elle-même, donc elle serait accessible avec Foo.Bar , comme ceci:

 public class Baz implements Foo.Bar {
   ...
}
 

Dans la plupart des cas, ceci n'est pas différent d'une classe interne statique.

6voto

user1982892 Points 61

Jesse la réponse est proche, mais je pense qu'il est mieux de code pour illustrer pourquoi un à l'intérieur de l'interface peut être utile. Regardez le code ci-dessous avant de vous lire. Pouvez-vous trouver pourquoi l'intérieur de l'interface est-elle utile? La réponse est que la classe DoSomethingAlready peut être instancié avec toute la classe qui implémente A et C, et pas seulement la classe concrète Zoo. Bien sûr, cela peut être réalisé même si CA n'est pas interne, mais imaginez la concaténation des noms plus longs (et pas seulement A et C), et de le faire pour d'autres combinaisons (disons A et B, C et B, etc.) et vous pouvez facilement voir comment les choses se passent hors de contrôle. Ne pas oublier que les gens de l'examen de votre arborescence des sources submergé par des interfaces qui n'ont de sens que dans une seule classe.Donc, pour résumer, un à l'intérieur de l'interface permet la construction de types personnalisés et améliore leur encapsulation.

class ConcreteA implements A {
 :
}

class ConcreteB implements B {
 :
}

class ConcreteC implements C {
 :
}

class Zoo implements A, C {
 :
}

class DoSomethingAlready {
  interface AC extends A, C { }

  private final AC ac;

  DoSomethingAlready(AC ac) {
    this.ac = ac;
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X