web-dev-qa-db-fra.com

classe interne dans l'interface

est-il possible de créer une classe interne dans une interface? Si oui, pourquoi créons-nous comme ça? De toute façon, nous ne créerons aucun objet d'interface?

Est-ce qu'ils aident dans un processus de développement?

79
gmhk

Oui, vous pouvez créer à la fois une classe imbriquée ou une classe interne dans une interface Java (notez que contrairement à la croyance populaire, il n’existe pas de "classe interne statique"; Il n'y a rien de classe "interne" ni de classe "externe" lorsqu'une classe imbriquée est statique, elle ne peut donc pas être "statique interne".

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

public interface A {
    class B {
    }
}

Je l'ai déjà vu mettre une sorte de "vérificateur de contrat" ​​directement dans la définition de l'interface (dans la classe imbriquée dans l'interface, il peut y avoir des méthodes statiques, contrairement à l'interface elle-même qui ne le peut pas). Ressemblant à 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 commente pas l'utilité d'une telle chose, je réponds simplement à votre question: cela peut être fait et c'est un type d'utilisation que j'ai vu en faire.

Maintenant, je ne ferai pas de commentaire sur l'utilité d'une telle construction et d'après ce que j'ai vu: je l'ai vue, mais ce n'est pas une construction très courante.

200KLOC codebase ici où cela se produit exactement à l'heure zéro (mais nous avons aussi beaucoup d'autres choses que nous considérons comme de mauvaises pratiques qui se produisent exactement à l'heure zéro et que d'autres personnes trouveraient parfaitement normales alors ...).

37
SyntaxT3rr0r

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

Ici, le code a deux classes imbriquées qui servent à encapsuler des informations sur les objets d'événement qui seront utilisés plus tard dans des définitions de méthodes comme getKeyEvents () Les avoir à l'intérieur de l'interface d'entrée améliore la cohésion.

92
zafar142003

Une utilisation valide, IMHO, définit les objets reçus ou renvoyés par les méthodes d’interface englobantes. Typiquement les structures de stockage de données. De cette façon, si l'objet n'est utilisé que pour cette interface, les choses sont plus cohérentes.

Par exemple:

interface UserChecker {
   Ticket validateUser(Credentials credentials);

   class Credentials {
      // user and password
   }

   class Ticket {
      // some obscure implementation
   }
}

Mais bon ... c'est juste une question de goût.

40
helios

Citation de la spécification Java 7 :

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

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

Il n'est PAS possible de déclarer des classes non statiques dans une interface Java, ce qui me semble logique.

28
Nad Nik

Un cas d’utilisation intéressant est de fournir une sorte de mise en œuvre 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 héritage). 

10
Bachi

C'est certainement possible, et un cas dans lequel j'ai trouvé cela utile est lorsqu'une interface doit lancer des exceptions personnalisées. Vous conservez les exceptions avec leur interface associée, ce qui, à mon avis, est souvent plus simple que de surcharger votre arborescence de sources avec des tas de fichiers d'exception triviaux.

interface MyInterface {

   public static class MyInterfaceException extends Exception {
   }

   void doSomething() throws MyInterfaceException;
}
7
Michael Anderson

Oui, il est possible d’avoir des définitions de classe statiques à l’intérieur d’une interface, mais l’aspect le plus utile de cette fonctionnalité concerne l’utilisation de types enum (qui sont un type spécial de classes statiques). Par exemple, vous pouvez avoir quelque chose comme ça:

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);
    ...
}
6
raspacorp

Ce que @Bachi mentionne est similaire aux traits de Scala et est réellement implémenté en utilisant une classe imbriquée dans une interface. Ceci peut être simulé en Java. Voir aussi Traits Java ou motif mixins?

1
Henno Vermeulen

Peut-être que si vous voulez des constructions plus complexes comme des comportements d'implémentation différents, 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 l'implémenté:

    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 des implémentations statiques, mais cela ne sera-t-il pas déroutant, je ne sais pas. 

1
Ilian Zapryanov

Vous pouvez également créer des classes statiques "Helper" pour des fonctionnalités communes aux objets qui implémentent cette interface:

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

J'en ai besoin d'un maintenant. J'ai une interface où il serait pratique de renvoyer une classe unique à partir 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 imbriquée statique, qui n’est associée qu’à cette interface, car cette interface doit être le seul endroit où cette classe de conteneur de résultats est créée.

0
user214420

Par exemple, traits (ressemblant à une interface avec des méthodes implémentées) dans Groovy Ils sont compilés dans une interface contenant une classe interne dans laquelle toutes les méthodes sont implémentées. 

0
dehasi

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.
  2. 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 dans ce cas comme un espace de noms.

0
Venkat K