2010-05-26 4 views
31

Ho un oggetto che memorizza alcuni dati in una lista. L'implementazione potrebbe cambiare in seguito e non voglio esporre l'implementazione interna all'utente finale. Tuttavia, l'utente deve avere la possibilità di modificare e accedere a questa raccolta di dati. Attualmente ho qualcosa di simile:È meglio usare Elenco o Raccolta?

public List<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(List<SomeDataType> data) { 
    this.data = data; 
} 

questo significa che ho lasciato i dettagli di implementazione interna di fuoriuscire? Dovrei farlo invece?

public Collection<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(Collection<SomeDataType> data) { 
    this.data = new ArrayList<SomeDataType>(data); 
} 
+9

Una cosa da tenere a mente è che se si restituisce la raccolta o l'elenco effettivo in questo modo, si consente a qualcun altro di fare tutto ciò che desidera, incluso l'eliminazione di elementi o addirittura la cancellazione dell'intera faccenda. Potrebbe essere meglio restituire un wrapper non modificabile o una copia dell'elenco. –

+1

@PaulTomblin true, ma è un overhead eccessivo e artificiale per il sistema. I wrapper non modificabili hanno senso quando si lavora con oggetti gestiti dal middleware di persistenza, e anche solo in rari casi. – comeGetSome

+0

@comeGetSome, è per questo che ho detto "può" piuttosto che "deve". Dipenderebbe dal caso d'uso: se dovessi creare un'API per altri utenti, restituirei una copia o un wrapper. Se fosse per me o per i colleghi di fiducia, metterei un grande "NON MODIFICARE QUESTO VALORE" nei javadoc e lascialo fare a quello. –

risposta

24

Dipende solo, vuoi che i tuoi utenti siano in grado di indicizzare i dati? Se sì, usa List. Entrambe sono interfacce, quindi non stai perdendo dettagli di implementazione, in realtà, devi solo decidere la funzionalità minima necessaria.

0

Se si trattasse di oscurare la rappresentazione interna dei miei dati a un utente esterno, utilizzerei XML o JSON. Ad ogni modo, sono abbastanza universali.

+0

significa sempre Tipo di restituzione stringa sempre? – erdogany

+0

Ovviamente. XML e JSON sono destinati ad essere piuttosto universali e cosa potrebbe essere più universale di una stringa? – Cyberherbalist

+2

Bene, se sto passando dati tra le app, userò una codifica di quel tipo. Ma se sto parlando di un valore di ritorno da una funzione ... convertirlo in XML, restituirlo come una stringa, e quindi il chiamante deve analizzare l'XML? È un sacco di complessità e sovraccarico solo per restituire un array. – Jay

1

Sì, la prima alternativa contiene i dettagli di implementazione di perdita se non fa parte del contratto di interfaccia che il metodo restituirà sempre un elenco. Inoltre, consentire al codice utente di sostituire l'istanza della raccolta è un po 'pericoloso, perché l'implementazione che hanno inoltrato potrebbe non funzionare come previsto.

Ovviamente, tutto dipende da quanto ti fidi dei tuoi utenti. Se prendi la filosofia di Python che "siamo tutti adulti consenzienti qui", allora il primo metodo va bene. Se pensi che la tua libreria sarà utilizzata da sviluppatori inesperti e dovrai fare tutto il possibile per "farli da babysitter" e assicurarti che non facciano qualcosa di sbagliato, allora è preferibile non lasciare che siano loro a impostare la raccolta e a non tornare nemmeno la collezione attuale. Invece restituire una copia (superficiale) di esso.

+1

java.util.Collections contiene metodi statici come unmodifiableList() che racchiudono semplicemente le raccolte in modo tale che tutti i metodi che modificano gli errori di restituzione della raccolta vengano invece sostituiti. Poiché l'istanziazione dei wrapper è un'operazione a tempo costante, è preferibile persino una copia superficiale (che il codice client può fare da sé se ha bisogno di una collezione mutevole). –

0

Dipende dalle garanzie che si desidera fornire all'utente. Se i dati sono sequenziali in modo tale che l'ordine degli elementi è importante e si stanno consentendo duplicati, utilizzare una lista. Se l'ordine degli elementi non ha importanza e i duplicati possono o non possono essere consentiti, utilizzare una raccolta. Dato che in effetti stai restituendo la raccolta sottostante non dovresti avere sia una funzione get che una funzione set, solo una funzione get, poiché la collezione restituita potrebbe essere mutata. Inoltre, fornire una funzione set consente al tipo di collezione di essere modificato dall'utente, mentre probabilmente si desidera che il tipo particolare sia controllato da voi.

5

L'utilizzo del tipo più generale, ovvero Raccolta, ha più senso a meno che non vi sia un motivo esplicito per utilizzare il tipo più specifico: Elenco. Ma qualunque cosa tu faccia, se questa è un'API per il consumo pubblico, è chiaro nella documentazione che cosa fa; se restituisce una copia superficiale della collezione, dillo.

7

Quando si restituisce un'implementazione di un'interfaccia o di una classe in una gerarchia alta, la regola generale è che il tipo di reso dichiarato deve essere il livello PIÙ ALTO che fornisce la funzionalità minima che si è pronti a garantire al chiamante, e che il chiamante ha ragionevolmente bisogno. Ad esempio, supponiamo che ciò che si restituisce veramente sia un ArrayList. ArrayList implementa List e Collection (tra le altre cose). Se si prevede che il chiamante debba utilizzare la funzione get (int x), quindi non funzionerà per restituire una raccolta, sarà necessario restituire una lista o ArrayList. Finché non si vede alcun motivo per cui si dovrebbe mai cambiare la propria implementazione per utilizzare qualcosa di diverso da una lista - ad esempio un Set - allora la risposta corretta è quella di restituire una Lista. Non sono sicuro che ci sia una funzione in ArrayList che non sia in List, ma se lo è, si applica lo stesso ragionamento. D'altra parte, una volta che si restituisce una lista invece di una raccolta, ora si è bloccati in una certa misura nell'implementazione. Meno inserisci la tua API, minore sarà la restrizione sui futuri miglioramenti.

(In pratica, ho quasi sempre restituire un elenco in tali situazioni, e mi ha mai bruciato. Ma probabilmente in realtà dovrebbe restituire un insieme.)

9

indipendente della capacità di indice della lista tramite List .get (int), gli utenti (o voi) si aspettano che gli elementi della collezione siano in un ordine affidabile e prevedibile? La collezione può avere multipli dello stesso articolo? Entrambe queste sono aspettative di liste che non sono comuni a raccolte più generali. Questi sono i test che uso per determinare quale astrazione esporre all'utente finale.

14

Il ritorno di una lista è in linea con la programmazione sull'interfaccia più adatta.

Il ritorno di una raccolta causerebbe ambiguità all'utente, poiché una raccolta restituita potrebbe essere: Imposta, Elenco o Coda.