2010-03-08 15 views
70

¿es posible crear una clase interna dentro de una interfaz? En caso afirmativo, ¿por qué creamos así? De todos modos, ¿no vamos a crear ningún objeto de interfaz?clase interna dentro de la interfaz

¿Lo ayudan en cualquier proceso de Desarrollo?

Respuesta

33

Sí, puede crear tanto una clase anidada o una clase interna dentro de una interfaz Java (nótese que contrariamente a la creencia popular que no hay tal cosa como un "clase interna estática": esto simplemente no tiene sentido, no hay nada "interno" ni ninguna clase "externa" cuando una clase anidada es estática, por lo que no puede ser "estática interna").

De todos modos, la siguiente compila bien:

public interface A { 
    class B { 
    } 
} 

que he visto que se usa para poner una especie de "corrector contrato" directamente en la definición de la interfaz (bueno, en la clase anidada en la interfaz, que puede tener métodos estáticos, al contrario de la interfaz en sí, que no puede). Se ve así si recuerdo correctamente.

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

Tenga en cuenta que yo no voy a hacer comentarios sobre la utilidad de tal cosa, estoy simplemente responder a su pregunta: ¿se puede hacer y esto es un tipo de uso que he visto hecho de ella.

Ahora no voy a comentar sobre la utilidad de tal construcción y de lo que he visto: lo he visto, pero no es una construcción muy común.

200KLOC base de código aquí donde ocurre exactamente el tiempo cero (pero luego tenemos muchas otras cosas que consideramos malas prácticas que pasan exactamente a cero tiempo que otras personas encontrarían perfectamente normales así que ...).

+0

¿Puede agregar algunos ejemplos de uso? He probado algo similar hace algún tiempo y no he entendido qué puedo ganar al usar esta construcción. – Roman

+0

@Roman: bueno recuerdo que me encontré con esto en algún proyecto (proyecto relativamente limpio, pero no era mío) pero no sé si está realmente limpio o no. He agregado un pequeño ejemplo que se parece a lo que he visto, pero una vez más: este no era mi código y no estoy usando esa construcción, por lo que no soy el más calificado para encontrar ejemplos válidos :) IIRC la clase dentro siempre fue nombrada, por ejemplo * StateChecker * y las llamadas siempre se verían así: * A.StateChecker.check (a) * o algo así. – SyntaxT3rr0r

+4

Si dice que "no existe una clase interna * * estática *", su respuesta de que "usted * puede * crear una clase anidada o una clase interna dentro de una interfaz Java" es fundamentalmente incorrecta. Usando su definición restringida, 'interface's * no * tiene clases internas. Puedes omitir el modificador 'static' de la clase anidada de' interface' pero aún así, es una clase anidada, no una clase interna. – Holger

37

Un uso válido, en mi humilde opinión, es la definición de objetos que son recibidos o devueltos por los métodos de interfaz adjuntos. Típicamente estructuras de retención de datos. De esa forma, si el objeto solo se usa para esa interfaz, tienes las cosas de una forma más cohesiva.

Por ejemplo:

interface UserChecker { 
    Ticket validateUser(Credentials credentials); 

    class Credentials { 
     // user and password 
    } 

    class Ticket { 
     // some obscure implementation 
    } 
} 

Pero de todos modos ... Es sólo una cuestión de gusto.

8

Un caso de uso interesante es proporcionar una especie de implementación predeterminada para los métodos de interfaz a través de una clase interna como se describe aquí: https://stackoverflow.com/a/3442218/454667 (para resolver el problema de la herencia de clase única).

1

Lo que @Bachi menciona es similar a los rasgos en Scala y en realidad se implementa utilizando una clase anidada dentro de una interfaz. Esto se puede simular en Java. Consulte también java traits or mixins pattern?

79

Sí, podemos tener clases dentro de las interfaces. Un ejemplo de uso podría ser

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

Aquí el código tiene dos clases anidadas que son para encapsular información acerca de los objetos de eventos que se utilizan más adelante en definiciones de métodos como getKeyEvents(). Tenerlos dentro de la interfaz de entrada mejora la cohesión.

+8

¡Buen ejemplo, esto debería tener más votos ascendentes! – Levit

+2

@Levit Solo me pregunto, ¿cómo se verá la clase implementada? – overexchange

+0

Me encantaría ver una implementación en acción para el uso anterior. Gracias. –

19

Cita de la Java 7 spec:

Interfaces pueden contener declaraciones de tipo miembro (§8.5).

Una declaración de tipo de miembro en una interfaz es implícitamente estática y pública. Se permite especificar redundantemente uno o ambos de estos modificadores.

No es posible declarar clases no estáticas dentro de una interfaz Java, lo cual tiene sentido para mí.

+0

Gracias. Esta es probablemente la respuesta más concisa de todas. – Joseph

7

Sin duda es posible, y un caso en el que he encontrado que es útil es cuando una interfaz tiene que lanzar excepciones personalizadas. Usted puede mantener las excepciones con su interfaz asociada, lo cual creo que a menudo es mejor que ensuciar su árbol de fuentes con montones de archivos de excepción triviales.

interface MyInterface { 

    public static class MyInterfaceException extends Exception { 
    } 

    void doSomething() throws MyInterfaceException; 
} 
6

Sí que es posible tener las definiciones de clases estáticas dentro de una interfaz, pero tal vez el aspecto más útil de esta función es cuando se usa tipos de enumeración (que son tipo especial de clases estáticas). Por ejemplo, puede tener algo como esto:

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

Encontré un abeto de uso este tipo de constructo.

  1. Puede usar esta construcción para definir y agrupar todas las constantes estáticas finales.
  2. Dado que es una interfaz, puede implementar esto en una clase.

Tiene acceso a todas las constantes agrupadas; el nombre de la clase actúa como espacio de nombres en este caso.

0

También puede crear "ayudante" clases estáticas para la funcionalidad común para los objetos que implementan esta interfaz:

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

Tal vez cuando se desea construcciones más complejas como algunos comportamientos diferentes de aplicación, tenga en cuenta:

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

esta es su interfaz y este será el 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(); 
    } 
} 

Puede proporcionar algunas implementaciones estáticas, pero no será confuso, no lo sé.

0

Necesito uno en este momento. Tengo una interfaz en la que sería conveniente devolver una clase única de varios de sus métodos. Esta clase solo tiene sentido como un contenedor para las respuestas de los métodos de esta interfaz.

Por lo tanto, sería conveniente tener una definición de clase anidada estática, que está asociada solo a esta interfaz, ya que esta interfaz debería ser el único lugar donde se crea esta clase de contenedor de resultados.

0

Por ejemplo traits (similar a la interfaz con los métodos implementados) en Groovy. Se compilan en una interfaz que contiene una clase interna donde se implementan todos los métodos.