2011-08-23 12 views
10

Va bene, so che è la regola:Perché l'interfaccia può essere dichiarata solo nella classe di primo livello?

Secondo JLS: 8.1.3 Classi interne e istanze di contenimento, interni classi non può dichiarare inizializzatori statici o interfacce membri. Le classi interne non possono dichiarare membri statici, a meno che non siano campi costanti in fase di compilazione .

Secondo 8.5.2 statici Member dichiarazioni, "interfacce Stati sono sempre implicitamente statica. E 'consentito, ma non richiesto per la dichiarazione di un'interfaccia utente per elencare in modo esplicito la statica modificatore". Sono sempre di alto livello, non interni.

Mi chiedo solo perché. Cosa può accadere se siamo autorizzati a dichiarare un'interfaccia all'interno di una classe interiore? La classe interna non diventerà una classe di alto livello se la inserirò in un altro file di classe?

risposta

7

La classe interna non diventa classe di livello superiore se la inserisco in un altro file di classe?

No, è ancora una classe interna, che indica il nome file (IIRC è OuterClass$InnerClass.class).

Le classi interne hanno accesso agli attributi della classe esterna, ovvero dipendono dall'istanza della loro classe esterna. Con le interfacce non potresti farlo. Pensa a una classe completamente indipendente che dovrebbe essere creata dall'istanza corrispondente della classe esterna. Come si farebbe se la classe esterna non sapesse chi implementa quell'interfaccia?

Che cosa si può fare è dichiarare interfacce statiche nella classe esterna, quindi semplicemente utilizzando l'esterno come uno spazio dei nomi:

public class OuterClass { 
    public static interface InnerInterface { //protected and private would be fine too, depending on what makes sense 
    } 
} 

Edit: in realtà, ho letto male la questione e dal momento che le interfacce sono statici in ogni modo, ecco un frammento di codice aggiornato:

public class OuterClass { 
    public static InnerClass { //static inner class making OuterClass just be a namespace 
    public interface InnerInnerInterface { //protected and private would be fine too, depending on what makes sense 
    } 
    } 
} 

Come una soluzione che si potrebbe definire una classe interna interna astratta, con lo svantaggio che è necessario attenersi al vincolo ereditarietà singola.

+0

Hmm, interessante! Non so mai che l'interfaccia possa essere dichiarata statica. Cosa significa "statico" qui? Ho provato l'interfaccia statica su Google ma non ho trovato nulla. P/s: basta modificare il mio post sulla linea che citi, per correggere l'errore di grammatica. –

+2

@ W.N .: Le interfacce sono implicitamente statiche. Quella dichiarazione è appena ridipinta. –

+1

@Ryan buon punto, ho anche solo riletto la domanda e aggiornerò la mia risposta. – Thomas

1

Le classi interne devono essere i dettagli di implementazione della classe di livello superiore e devono pertanto essere invisibili al client. Qualsiasi funzionalità a cui desideri accedere di una classe interna deve essere eseguita tramite la classe di livello superiore, perché concettualmente, tale funzionalità dovrebbe essere visibile solo come funzionalità della classe di livello superiore, in modo che il progettista della classe possa scambiare o altrimenti cambiare drasticamente le classi interne senza rompere le build dei clienti.

+2

Questa è solo una questione di opinione. Se le classi interne fossero solo per uso interno della classe genitore, non ti sarebbe permesso renderle "pubbliche". – skaffman

2

Per definizione una classe di alto livello e le sue classi interne sono strettamente accoppiate. Le interfacce sono un mezzo per ridurre l'accoppiamento.

+1

Anche se ho solo bisogno di usare privatamente quell'interfaccia per la classe interna? –

+0

Questo non è necessariamente un buon argomento, dal momento che ho scritto un numero di interfacce nidificate private che vengono utilizzate solo nell'ambito di una singola classe. –

4

Pensateci in termini di contesto statico o non statico. Una classe "di primo livello" stabilisce un contesto statico perché è possibile accedervi senza alcuna istanza di inclusione. Cioè puoi accedere alle classi di alto livello da un metodo principale. Lo stesso vale per qualsiasi membro statico di una classe di livello superiore. Una classe interna, tuttavia, non esiste né in * né stabilisce alcun contesto statico. Pertanto non può avere membri statici e può essere accessibile solo tramite un'istanza della sua classe contenente, come costruttori e altri membri di istanza. Da un metodo principale, non potresti dire Outer.Inner.SOME_FIELD perché i membri di una classe interna hanno solo un significato rispetto alla classe contenente.

* tipo di

+0

Questa risposta renderà più chiara la risposta di Thomas. +1. –

Problemi correlati