2009-02-27 7 views

Respuesta

18

Puedo pensar en otro uso distinto de los vinculados por Eric P: definir una implementación predeterminada/no operativa de la interfaz.

./alex

interface IEmployee 
{ 

    void workHard(); 
    void procrastinate(); 

    class DefaultEmployee implements IEmployee 
    { 
     void workHard() { procrastinate(); }; 
     void procrastinate() {}; 
    } 

} 

Sin embargo, otro ejemplo - la aplicación de Null Object Pattern:

interface IFoo 
{ 
    void doFoo(); 
    IFoo NULL_FOO = new NullFoo(); 

    final class NullFoo implements IFoo 
    { 
     public void doFoo() {}; 
     private NullFoo() {}; 
    } 
} 


... 
IFoo foo = IFoo.NULL_FOO; 
... 
bar.addFooListener (foo); 
... 
+0

Ooh, me gusta la idea. – Herms

+0

@Totophil: me alegro de que hayas tenido la idea y gracias por mejorar mi respuesta. @Herms: ¡me alegro de que te guste! – alexpopescu

+1

Comúnmente el objeto nulo podría ser un singleton también, ya que no se mantiene en ningún estado ni muta ningún otro objeto; esta es en realidad una gran respuesta ya que voy a empezar a hacer cosas como esta a partir de ahora, ¡esto es inteligente! – Esko

5

puedo decir sin duda que nunca he hecho eso. No puedo pensar en una razón por la que tampoco lo harías. Clases anidadas dentro de las clases? Claro, hay muchas razones para hacer eso. En esos casos, tiendo a considerar esas clases internas como un detalle de implementación. Obviamente, una interfaz no tiene detalles de implementación.

8

Creo que this page explica un ejemplo bastante bien. Lo usarías para unir fuertemente un cierto tipo a una interfaz.

Desvergonzadamente estafado desde el enlace anterior:

interface employee{ 
    class Role{ 
      public String rolename; 
      public int roleId; 
    } 
    Role getRole(); 
    // other methods 
} 

En la interfaz anterior va a enlazar el papel de tipo fuertemente a la interfaz empleado (employee.Role).

2

Supongo que podría definir una clase que se utiliza como tipo de retorno o tipo de parámetro para los métodos dentro de la interfaz. No parece particularmente útil. También podría definir la clase por separado. La única ventaja posible es que declara la clase como "perteneciente" a la interfaz en algún sentido.

1

Al hacer esto parece haber escrito "Mala decisión de diseño" escrita por todas partes.

1

Insto cuidado siempre que se parece como una buena idea crear una clase anidada no privado. Es casi seguro que es mejor ir directamente a una clase exterior. Pero si vas a crear una clase anidada pública, no parece más extraño ponerla en una interfaz que en una clase. La abstracción de la clase externa no está necesariamente relacionada con la abstracción de una clase anidada.

2

Google Web Toolkit utiliza estas clases de obligar interfaz de 'normal' a la interfaz de llamada asincrónica:

public interface LoginService extends RemoteService { 

    /** 
    * Utility/Convenience class. 
    * Use LoginService.App.getInstance() to access static instance of LoginServiceAsync 
    */ 
    class App { 

     public static synchronized LoginServiceAsync getInstance() { 
      ... 
     } 
    } 
} 
6

Uno de los usos (para mejor o peor) sería como una solución para el hecho de que Java no soporta métodos estáticos en las interfaces.

interface Foo { 
    int[] getData(); 

    class _ { 
     static int sum(Foo foo) { 
      int sum = 0; 
      for(int i: foo.getData()) { 
       sum += i; 
      } 
      return sum; 
     } 
    } 
} 

Luego que se dice con:

int sum = Foo._.sum(myFoo); 
+0

Eso es tan peor que tengo que votarlo. Amo este tipo de experimentos. – akuhn

+1

Tienes que estar bromeando. Dejan que compile ???!?!? (bueno, por cierto) – Overflown

3

Un lugar este lenguaje se utiliza en gran medida está en XMLBeans. El objetivo de ese proyecto es tomar un Esquema XML y generar un conjunto de clases de Java que puede usar de forma bidireccional para trabajar con documentos XML correspondientes al esquema. Por lo tanto, le permite analizar XML en beans xml o crear beans xml y enviarlos a xml.

En general, la mayoría de los tipos de esquema xml se asignan a una interfaz Java.Esa interfaz tiene en su interior una fábrica que se utiliza para generar instancias de dicha interfaz en la implementación por defecto:

public interface Foo extends XmlObject { 
    public boolean getBar(); 
    public boolean isSetBar(); 
    public void setBar(boolean bar); 

    public static final SchemaType type = ... 

    public static final class Factory { 
    public static Foo newInstance() { 
     return (Foo)XmlBeans.getContextTypeLoader().newInstance(Foo.type, null); 
    } 

    // other factory and parsing methods 
    } 
} 

Cuando me encontré por primera vez este parecía mal para unir toda esta porquería aplicación en la definición de interfaz. Sin embargo, en realidad cada vez me gusta más, ya que permite que todo se defina en términos de interfaces, pero tiene una manera uniforme de obtener instancias de la interfaz (en lugar de tener otra clase externa de fábrica/generador).

Lo recogí para las clases donde esto tenía sentido (particularmente aquellas en las que tenía un gran control sobre la interfaz/impls) y me pareció bastante limpio.

1

Este enfoque se puede utilizar para definir muchas clases en el mismo archivo. Esto funcionó bien para mí en el pasado, donde tengo muchas implementaciones simples de una interfaz. Sin embargo, si tuviera que hacer esto de nuevo, usaría una enumeración que implementa una interfaz que habría sido una solución más elegante.

+0

ocultar comentarios Estaba pensando en la implementación a través de enum también, pero dado que cualquier enumeración es efectivamente una colección de singletons que estaba luchando por pensar en cualquier muestra de la vida real, a cualquiera le gustaría un montón de "default" implementación singletons para la misma interfaz. –

2

Con una clase estática dentro de una interfaz, tiene la posibilidad de acortar un fragmento de programación común: comprobar si un objeto es una instancia de una interfaz y, si es así, llamar a un método de esta interfaz. Mira este ejemplo:

public interface Printable { 
    void print(); 

    public static class Caller { 
     public static void print(Object mightBePrintable) { 
      if (mightBePrintable instanceof Printable) { 
       ((Printable) mightBePrintable).print(); 
      } 
     } 
    } 
} 

Ahora, en lugar de hacer esto:

void genericPrintMethod(Object obj) { 
    if (obj instanceof Printable) { 
     ((Printable) obj).print(); 
    } 
} 

puede escribir:

void genericPrintMethod(Object obj) { 
    Printable.Caller.print(obj); 
} 
Cuestiones relacionadas