2012-09-27 15 views
8

Recentemente, ho avuto l'occasione di utilizzare il costrutto Java <instance>.new per creare un'istanza di una classe interna.Il punto di Java è un nuovo odore di codice?

Mentre sento che ci fosse una giustificazione ragionevole farlo, la sua sintassi piuttosto oscuro sembra che potrebbe rendere le cose un po 'più difficile da comprendere per i programmatori di manutenzione.

Ma mi chiedo se la necessità di <esempio> .new è un indicatore che sarebbe meglio fare un po 'di refactoring per rendere la classe interna di una classe di livello nella confezione del suo genitore, dargli un costruttore che prendere un riferimento al suo tipo genitore sarebbe più ideale e aggiungere metodi di accesso o modificatori di accesso a livello di pacchetto ai campi che accede dal tipo genitore.

Esistono casi d'uso per l'istanza < >. Nuovo che non è stato possibile eseguire eseguendo il refactoring della classe interna in una classe esterna?

risposta

2

non avrebbe detto che era necessariamente il codice odore.

Se l'accoppiamento tra le classi esterne ed interne è forte, e l'utilizzo della classe interno rappresenta un buon incapsulamento, allora direi che l'utilizzo di questo costrutto è giustificata. D'altra parte, se l'astrazione ha già delle perdite, quindi rendere la classe interna una classe di alto livello è probabilmente un'idea migliore.

L'utilizzo di outer.new Inner() può o non può essere la prova di un'astrazione che perde.

(Il costrutto è stato incluso nella lingua per una buona ragione, e il fatto che esso è raramente necessaria non invalida il suo utilizzo.)

+0

Potrebbe essere solo il mio caso d'uso, ma sembra che la necessità di istanziare una classe interna al di fuori del suo genitore indica che il livello di incapsulamento potrebbe non essere appropriato. Cosa dovrei cercare per determinare se l'incapsulamento è appropriato? – Kylos

+1

Valuta se la classe interna è "interna" alla classe esterna. Considerare se la classe interna possa essere utilizzata in modo significativo indipendentemente da un'istanza di classe esterna. –

+0

Fondamentalmente, mi chiedo se la necessità di utilizzare una classe interna al di fuori della sua classe contenente indica che una classe interna potrebbe non essere l'incapsulamento appropriato. – Kylos

4

Esistono casi di utilizzo per .new che non possono essere gestiti rifasando la classe interna a una classe esterna?

non ci sono generalmente importanti casi d'uso per che la sintassi, come si può sempre nascondere il costruttore interiore e lasciare che la classe esterna restituire istanze di classe interiori attraverso metodi di fabbrica (se si ha intenzione di rivelare il tipo di interno verso l'esterno in ogni caso):

public class Outer { 
    public class Inner { 
     private Inner() {} 
    } 

    public Inner createInner() { 
     return new Inner(); 
    } 
} 

codice cliente:

Outer outer = new Outer(); 
Inner inner = outer.createInner(); 

Così il "codice di odore" (se è davvero un codice odore) non è nel fatto che una classe interna è presente, ma nel fatto che il suo c onstructor è disponibile pubblicamente (e utilizzato). Ma dopo un'attenta valutazione, si potrebbe capire che questo è OK

UPDATE: Un buon segno che mostra che l'incapsulamento è rotto è quando Outer casi probabilmente hanno una vita più breve rispetto Inner istanze. In tal caso, Inner casi possono tenere un riferimento a Outer per un periodo di tempo di quanto autore s' il Outer destinato più a lungo. Questo può anche portare a perdite di memoria.

+0

Grazie. Questi sono alcuni buoni pensieri. – Kylos

0

Ebbene, da una classe interna si ha accesso ai membri privati ​​di la classe esterna. Le classi di livello superiore no.

Ma si potrebbe aggiungere un metodo factory per la classe esterna, che crea una nuova istanza della classe interna.

+0

Vero. Liberarsi della classe interna richiederebbe l'accesso a livello di pacchetto al minimo, quindi se l'accesso ai membri privati ​​è importante, sarebbe necessaria una classe interna. – Kylos

0

Utilizzando classi interne rende il codice più difficile da capire, perché le classi condividono il loro stato interiore, e quindi rompere il principio di nascondere informazioni. A volte usare una classe interiore può rendere facile una soluzione per scrivere, ma penso che non sia la soluzione migliore/più pulita la maggior parte delle volte.

+0

[classi interne sono sempre le classi annidate non statici] (http://docs.oracle.com/javase/tutorial/java/javaOO/summarynested.html) –

+0

ho scritto "annidata", ma poi lo ha sostituito con interiore. fissa – CQQL

+0

Beh, almeno anonima classi interne (che è certamente fuori tema qui, dal momento che non dispone di un costruttore di chiamare da "fuori"), sono abbastanza comuni per implementare gli ascoltatori ad esempio nel codice GUI. Anche se potrebbero essere sostituiti una volta che avremo espressioni lambda in Java (attualmente pianificate per Java SE 8). – Puce

0

Io uso classe interna espescially quando un metodo di una classe deve essere multithreading.

In effetti, ci sono due modi puliti di discussioni dichiarando:

  • creare una classe Runnable (che contiene il metodo di ottenere multithreaded) e lasciare che il cliente instanciate un nuovo thread se stesso. Lo svantaggio è che il cliente deve essere consapevole del fatto che deve affrontare il multithreading.

  • Non dichiarare la classe di lavoro come Runnable, ma si preferisce definire unche è esso stesso in esecuzione Runnable. Naturalmente, questo non ha inner-class devono essere public e quindi è istanziare da uno dei metodo dedicato pubblico nella classe esterna (cioè la categoria di lavoro). Quindi, il client si occupa di questo metodo public senza sapere che un thread è stato creato in background. Se domani gli sviluppatori scelgono di rimuovere il multithreading all'interno di questa classe di lavoro per qualsiasi motivo, il client può essere completamente mantenuto invariato.

E per consentire a questa classe interna di ereditare i campi della classe esterna, non la dichiaro statica. (Chiamato anche classe innestata al contrario di classe interna)

Problemi correlati