Lato pratico della capacità di definire una classe all'interno di un'interfaccia in Java?

StackOverflow https://stackoverflow.com/questions/594789

  •  09-09-2019
  •  | 
  •  

Domanda

Quale sarebbe il lato pratico della capacità di definire una classe all'interno di un'interfaccia in Java:

interface IFoo
{
    class Bar
    {
        void foobar ()
        {
            System.out.println("foobaring...");
        }
    }
}
È stato utile?

Soluzione

mi viene in mente un altro utilizzo di quelli legati da Eric P: la definizione di un'implementazione di default / no-op dell'interfaccia

.

./ alex

interface IEmployee
{

    void workHard ();  
    void procrastinate ();

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

}

Ancora un altro esempio - l'attuazione del modello Null Object :

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);
...

Altri suggerimenti

Penso questa pagina spiega un esempio abbastanza bene.Si dovrebbe utilizzare per ben si legano ad un certo tipo di interfaccia.

Spudoratamente strappato dal link sopra:

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

L'interfaccia di cui sopra si sono vincolanti per il tipo di Ruolo fortemente dipendente interfaccia(dipendente.Ruolo).

sarebbe Un uso (bene o male) come una soluzione per il fatto che Java non supporta metodi statici nelle interfacce.

interface Foo {
    int[] getData();

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

Poi si definirebbe con:

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

Posso dire senza esitazione che non ho mai fatto questo. Non riesco a pensare a una ragione per cui si farebbe neanche. Classi annidate all'interno delle classi? Certo, un sacco di motivi per farlo. In tali casi tendo a considerare tali classi interne di essere un dettaglio implementativo. Ovviamente un'interfaccia non ha dettagli di implementazione.

Un posto questo idioma è usato pesantemente è in XMLBeans . Lo scopo di tale progetto è quello di prendere uno schema XML e generare un insieme di classi Java che è possibile utilizzare in modo bidirezionale per lavorare con i documenti XML che corrispondono allo schema. Quindi, consente di analizzare XML in fagioli XML o creare i fagioli e output XML in XML.

In generale, la maggior parte dei tipi di schema XML sono mappati ad un'interfaccia Java. Quella interfaccia ha al suo interno una fabbrica che viene utilizzato per generare le istanze di tale interfaccia nella implementazione di default:

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

Quando ho incontrato prima questo mi è sembrato sbagliato legare tutto questo gunk implementazione nella definizione dell'interfaccia. Tuttavia, in realtà ho cresciuto a piacermi come lasciare che tutto ottiene definito in termini di interfacce, ma hanno un modo uniforme per ottenere istanze di interfaccia (al contrario di avere un altro class factory / costruttore esterno).

Lo presi per classi dove questo fatto senso (in particolare quelli in cui avevo una grande quantità di controllo sull'interfaccia / impls) e trovata per essere abbastanza pulito.

Credo che si potrebbe definire una classe che viene utilizzata come tipo di ritorno o tipo di parametro per i metodi all'interno dell'interfaccia. Non sembra particolarmente utile. Si potrebbe anche solo definire la classe a parte. L'unico vantaggio possibile è che si dichiara la classe come "appartenenza" per l'interfaccia in un certo senso.

Google Web Toolkit utilizza tali classi di legare l'interfaccia 'normale' per l'interfaccia chiamata asincrona:

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() {
            ...
        }
    }
}

Con una classe statica all'interno un'interfaccia si ha la possibilità di accorciare un frammento di programmazione comune: Verifica se un oggetto è un'istanza di un'interfaccia, e se così chiamando un metodo di questa interfaccia. Guarda questo esempio:

public interface Printable {
    void print();

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

Ora, invece di fare questo:

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

È possibile scrivere:

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

In questo modo sembra avere "Bad decisione di design", scritto tutto su di esso.

Esorto cautela ogni volta che sembra una buona idea per creare una classe non-privato nidificato. Lei è quasi certamente meglio andare dritto per una classe esterna. Ma se avete intenzione di creare una classe annidata pubblico, non sembra più strano di metterla in un'interfaccia di una classe. L'astrattezza della classe esterna non è necessariamente legato alla astrattezza di una classe annidata.

Questo approccio può essere utilizzato per definire molte classi nello stesso file. Questo ha funzionato bene per me in passato, dove ho molti semplici implementazioni di un'interfaccia. Tuttavia, se dovessi farlo di nuovo, vorrei utilizzare un enum che implementa un'interfaccia che sarebbe stata una soluzione più elegante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top