2010-03-08 2 views
70

est que possible de créer une classe interne au sein d'une interface? Si oui, pourquoi créons-nous comme ça? De toute façon, nous n'allons pas créer d'objets d'interface?classe interne à l'intérieur de l'interface

aident-ils dans tout processus de développement?

Répondre

33

Oui, vous peut créer à la fois une classe imbriquée ou une classe interne à l'intérieur d'une interface Java (notez que contrairement à la croyance populaire, il n'y a pas une telle chose comme une « classe interne statique »: cela n'a aucun sens, il n'y a rien de "interne" et pas de "externe" quand une classe imbriquée est statique, donc elle ne peut pas être "statique interne").

Quoi qu'il en soit, ce qui suit compile bien:

public interface A { 
    class B { 
    } 
} 

Je l'ai vu utilisé pour mettre une sorte de « vérificateur de contrat » directement dans la définition d'interface (bien, dans la classe imbriquée dans l'interface, que peut avoir des méthodes statiques, contrairement à l'interface elle-même, qui ne peut pas). Cela ressemble à ceci si je me souviens bien.

public interface A { 
    static class B { 
     public static boolean verifyState(A a) { 
      return (true if object implementing class A looks to be in a valid state) 
     } 
    } 
} 

Notez que je ne suis pas de commentaires sur l'utilité d'une telle chose, je suis tout simplement répondre à votre question: il peut être fait et c'est un type d'utilisation que j'ai vu fait.

Maintenant, je ne commenterai pas l'utilité d'une telle construction et de je l'ai vu: Je l'ai vu, mais ce n'est pas une construction très courante. Codebase ici où cela arrive exactement zéro temps (mais nous avons beaucoup d'autres choses que nous considérons les mauvaises pratiques qui se produisent exactement à zéro heure que d'autres personnes trouveraient parfaitement normal alors ...).

+0

Pouvez-vous ajouter quelques exemples d'utilisation? J'ai testé quelque chose de similaire il y a quelque temps et je n'ai pas compris ce que je pourrais gagner en utilisant cette construction. – Roman

+0

@Roman: eh bien je me souviens d'avoir rencontré ça sur un projet (un projet relativement propre ajouterais-je mais qui n'était pas le mien) mais je ne sais pas si c'est vraiment propre ou pas. J'ai ajouté un petit exemple qui ressemble à ce que j'ai vu mais encore une fois: ce n'était pas mon code et je n'utilise pas cette construction donc je ne suis pas le plus qualifié pour trouver des exemples valides :) IIRC la classe à l'intérieur était toujours nommée, par exemple * StateChecker * et les appels ressembleraient toujours à: * A.StateChecker.check (a) * ou quelque chose comme ça. – SyntaxT3rr0r

+4

Si vous dites "il n'y a pas de" classe interne statique * "" votre réponse que "vous * pouvez * créer à la fois une classe imbriquée ou une classe interne dans une interface Java" est fondamentalement fausse. En utilisant votre définition rétrécie, 'interface's ne peut * pas * avoir de classes internes. Vous pouvez omettre le modificateur 'static' de la classe imbriquée d'une' interface' mais c'est quand même une classe imbriquée, pas une classe interne. – Holger

37

Utilisation valide, IMHO, est la définition d'objets qui sont reçus ou renvoyés par les méthodes d'interface englobant. Typiquement, des structures de stockage de données. De cette façon, si l'objet est seulement utilisé pour cette interface, vous avez des choses de manière plus cohérente.

Par exemple:

interface UserChecker { 
    Ticket validateUser(Credentials credentials); 

    class Credentials { 
     // user and password 
    } 

    class Ticket { 
     // some obscure implementation 
    } 
} 

Mais quand même ... il est seulement une question de goût.

8

Un cas d'utilisation intéressant est de fournir une sorte d'implémentation par défaut aux méthodes d'interface via une classe interne comme décrit ici: https://stackoverflow.com/a/3442218/454667 (pour résoudre le problème de l'héritage de classe unique).

1

Ce que @Bachi mentionne est semblable à des traits de Scala et sont effectivement mises en œuvre en utilisant une classe imbriquée dans une interface. Cela peut être simulé en Java. Voir aussi java traits or mixins pattern?

79

Oui, nous pouvons avoir des classes à l'intérieur des interfaces. Un exemple d'utilisation pourrait être

public interface Input 
{ 
    public static class KeyEvent { 
     public static final int KEY_DOWN = 0; 
     public static final int KEY_UP = 1; 
     public int type; 
     public int keyCode; 
     public char keyChar; 
    } 
    public static class TouchEvent { 
     public static final int TOUCH_DOWN = 0; 
     public static final int TOUCH_UP = 1; 
     public static final int TOUCH_DRAGGED = 2; 
     public int type; 
     public int x, y; 
     public int pointer; 
    } 
    public boolean isKeyPressed(int keyCode); 
    public boolean isTouchDown(int pointer); 
    public int getTouchX(int pointer); 
    public int getTouchY(int pointer); 
    public float getAccelX(); 
    public float getAccelY(); 
    public float getAccelZ(); 
    public List<KeyEvent> getKeyEvents(); 
    public List<TouchEvent> getTouchEvents(); 
} 

Voici le code a deux classes imbriquées qui sont pour l'encapsulation des informations sur les objets d'événements qui sont ensuite utilisés dans les définitions de méthode comme getKeyEvents(). Les avoir à l'intérieur de l'interface d'entrée améliore la cohésion.

+8

Vraiment bel exemple, cela devrait avoir plus de votes upvotes! – Levit

+2

@Levit Je me demandais juste à quoi ressemblerait la classe implémentée? – overexchange

+0

Aimerais voir une implémentation en action pour l'utilisation ci-dessus. Je vous remercie. –

19

Citation de la Java 7 spec:

interfaces peuvent contenir des déclarations de type de membre (§8.5).

Une déclaration de type de membre dans une interface est implicitement statique et publique. Il est permis de spécifier de manière redondante l'un de ces modificateurs ou les deux.

Il n'est pas possible de déclarer des classes non statiques à l'intérieur d'une interface Java, ce qui est logique pour moi.

+0

Merci. C'est probablement la réponse la plus concise de tous. – Joseph

7

C'est certainement possible, et un cas où j'ai trouvé cela utile est quand une interface doit lancer des exceptions personnalisées. Vous gardez les exceptions avec leur interface associée, ce qui, je pense, est souvent plus propre que d'encombrer votre arborescence source avec des tas de fichiers d'exceptions triviales.

interface MyInterface { 

    public static class MyInterfaceException extends Exception { 
    } 

    void doSomething() throws MyInterfaceException; 
} 
6

Oui, il est possible d'avoir des définitions de classe statique à l'intérieur d'une interface, mais peut-être l'aspect le plus utile de cette fonctionnalité est lorsque vous utilisez les types de ENUM (qui sont un peu spéciales des classes statiques). Par exemple, vous pouvez avoir quelque chose comme ceci:

public interface User { 
    public enum Role { 
     ADMIN("administrator"), 
     EDITOR("editor"), 
     VANILLA("regular user"); 

     private String description; 

     private Role(String description) { 
      this.description = description; 
     } 

     public String getDescription() { 
      return description; 
     } 
    } 

    public String getName(); 
    public void setName(String name); 
    public Role getRole(); 
    public void setRole(Role role); 
    ... 
} 
0

J'ai trouvé une utilisation de ce type de construction.

  1. Vous pouvez utiliser cette construction pour définir et regrouper toutes les constantes finales statiques. Depuis, c'est une interface que vous pouvez implémenter sur une classe.

Vous avez accès à toutes les constantes groupées; nom de la classe agit comme un espace de noms dans ce cas.

0

Vous pouvez également créer des classes statiques « aide » pour des fonctionnalités communes pour les objets qui mettent en œuvre cette interface:

public interface A { 
    static class Helper { 
     public static void commonlyUsedMethod(A a) { 
      ... 
     } 
    } 
} 
1

Peut-être quand vous voulez des constructions plus complexes comme des comportements différents de mise en œuvre, considérez:

public interface A { 
    public void foo(); 
    public static class B implements A{ 
     @Override 
     public void foo(){ 
      System.out.println("B foo"); 
     } 
    } 
} 

Ceci est votre interface et ce sera le implementee:

public class C implements A { 
    @Override 
    public void foo(){ A.B b = new A.B(); b.foo(); } 


    public static void main(String[] strings) { 
     C c = new C(); 
     c.foo(); 
    } 
} 

Peut fournir quelques implémentations statiques, mais cela ne sera pas confus, je ne sais pas.

0

J'en ai besoin en ce moment. J'ai une interface où il serait commode de retourner une classe unique de plusieurs de ses méthodes. Cette classe n'a de sens que en tant que conteneur pour les réponses des méthodes de cette interface. Par conséquent, il serait pratique d'avoir une définition de classe statique imbriquée, qui n'est associée qu'à cette interface, puisque cette interface devrait être le seul endroit où cette classe de conteneur de résultats est jamais créée.

0

Par exemple traits (interface de type smth avec des méthodes implémentées) dans Groovy. Ils sont compilés à une interface qui contient la classe interne où toutes les méthodes sont implémentées.

Questions connexes