2009-09-27 19 views
17

Questa è una vera domanda per principianti (sto ancora imparando le basi Java).Perché le variabili dichiarate con il loro nome di interfaccia in Java?

posso (o quasi) a capire perché i metodi dovrebbero restituire una lista <String> piuttosto che un ArrayList <String>, o perché dovrebbero accettare un parametro di elenco, piuttosto che un ArrayList. Se non fa alcuna differenza per il metodo (cioè, se non sono richiesti metodi speciali da ArrayList), ciò renderebbe il metodo più flessibile e più facile da usare per i chiamanti. La stessa cosa vale per altri tipi di raccolta, come Set o Mappa.

Quello che non capisco: sembra essere pratica comune per creare le variabili locali come questo:

List<String> list = new ArrayList<String>(); 

Anche se questa forma è meno frequente:

ArrayList<String> list = new ArrayList<String>(); 

Qual è il vantaggio qui?

Tutto quello che posso vedere è uno svantaggio minore: è necessario aggiungere una riga "import" separata per java.util.List. Tecnicamente, "import java.util. *" Potrebbe essere usato, ma non lo vedo molto spesso, probabilmente perché le linee di "importazione" vengono aggiunte automaticamente da qualche IDE.

risposta

20

Quando si legge

List<String> list = new ArrayList<String>(); 

si ottiene l'idea che tutto ciò che interessa è essere un List<String> e mettere meno enfasi sulla effettiva attuazione. Inoltre, ti limiti ai membri dichiarati da List<String> e non alla particolare implementazione. Non ti importa se i tuoi dati sono archiviati in un array lineare o in qualche struttura di dati di fantasia, a patto che assomigli a uno List<String>.

D'altra parte, la lettura della seconda riga ti dà l'idea che il codice si preoccupi della variabile sulla variabile ArrayList<String>. Scrivendo questo, stai implicitamente dicendo (ai futuri lettori) che non dovresti cambiare ciecamente il tipo di oggetto reale perché il resto del codice si basa sul sul fatto che si tratta in realtà di uno ArrayList<String>.

+5

Questo è abstractofilia. Le efficienze di un'implementazione rispetto a un'altra dipendono dal codice che _usatta_la variabile: non riesco a vedere che vorrei mai qualcosa ma un accoppiamento stretto tra i due. –

+0

"Non riesco a vedere che vorrei mai qualcosa di diverso da un accoppiamento stretto tra i due": l'intero concetto di interfacce non è basato sul fatto che in realtà ** vuoi ** un accoppiamento lento? –

+1

Ovviamente.Ma quando vorresti un accoppiamento lento tra il lavoro di una funzione e le sue variabili locali? Soprattutto quando si seleziona un'implementazione di una raccolta, poiché le raccolte sono spesso ottimizzate per situazioni specifiche. –

1

se in seguito si desidera modificare l'implementazione dell'elenco e utilizzare ad esempio LinkedList (forse per prestazioni migliori) non è necessario modificare l'intero codice (e l'API se la sua libreria). se l'ordine non ha importanza, devi restituire la Raccolta in un secondo momento, puoi facilmente cambiarla in Set se ti occorrono elementi da ordinare.

+0

"perché i metodi restituiscono un elenco anziché un ArrayList " <- quindi la sua API;) – IAdapter

1

La spiegazione migliore che riesco a trovare (perché non programma in Java con la frequenza che nelle altre lingue) è che semplifica il cambio del tipo di elenco "back-end" mantenendo lo stesso codice/interfaccia su cui tutto il resto si basa. Se prima lo si dichiara come un tipo più specifico, in seguito si decide di volere un tipo diverso ... se succede qualcosa usare un metodo specifico per ArrayList, è un lavoro extra.

Ovviamente, se in realtà è necessario il comportamento specifico di ArrayList, si utilizzerà invece il tipo di variabile specifico.

7

L'utilizzo dell'interfaccia consente di modificare rapidamente l'implementazione sottostante di Elenco/Mappa/Imposta/ecc.

Non si tratta di salvare le sequenze di tasti, si tratta di modificare rapidamente l'implementazione.Idealmente, non dovresti esporre i metodi specifici sottostanti all'implementazione e utilizzare semplicemente l'interfaccia richiesta.

2

Suggerirei di pensare a questo dall'altra parte. Di solito vuoi un elenco o un set o qualsiasi altro tipo di raccolta - e davvero non ti interessa nel tuo codice come esattamente questo è implementato. Quindi il tuo codice funziona solo con una lista e fa tutto ciò che deve fare (anche formulato come "sempre il codice per le interfacce").

Quando si creare l'Elenco, è necessario decidere quale implementazione effettiva si desidera. Per la maggior parte degli scopi ArrayList è "abbastanza buono", ma il tuo codice non gli interessa davvero. Continuando a utilizzare l'interfaccia, la trasmetti al futuro lettore.

Ad esempio, ho l'abitudine di avere il codice di debug nel mio metodo principale che scarica le proprietà di sistema su System.out - di solito è molto più carino ordinarle. Il modo più semplice è semplicemente "Mappa mappa = nuova TreeMap (proprietà);" e poi iterare attraverso di loro, come TreeMap restituisce le chiavi in ​​ordine.

Quando si impara di più su Java, si vedrà anche che le interfacce sono molto utili in testing e mocking, dal momento che è possibile creare oggetti con comportamento specificato in runtime conforme a una determinata interfaccia. Un esempio avanzato (ma semplice) può essere visto a http://www.exampledepot.com/egs/java.lang.reflect/ProxyClass.html

-2

Fondamentalmente questo proviene da persone che devono eseguire progetti di grandi dimensioni, possibilmente altri motivi - lo sentite sempre. Perché, in realtà non lo so. Se hai bisogno di un elenco di array, o Hash Map o Hash Set o qualsiasi altra cosa, non vedo alcun punto nell'eliminare i metodi eseguendo il casting su un'interfaccia.

Diciamo per esempio, di recente ho imparato come utilizzare e implementare HashSet come una struttura di dati principale. Supponiamo, per qualsiasi ragione, che io sia andato a lavorare in una squadra. Questa persona non avrebbe bisogno di sapere che i dati erano basati su un approccio di hashing piuttosto che essere ordinati da qualche base? L'approccio back-end notato da Twisol funziona in C/C++ dove puoi esporre le intestazioni e vendere una libreria in tal modo, se qualcuno sa come farlo in Java, immagino che utilizzerebbero JNI - a quel punto mi sembra più semplice utilizzare C/C++ in cui è possibile esporre le intestazioni e creare librerie utilizzando strumenti stabiliti a tale scopo.

Nel momento in cui è possibile ottenere qualcuno che può installare un file jar nella directory delle estensioni, mi sembra che l'entità potrebbe essere a pochi passi di distanza - Ho lasciato cadere diverse librerie crittografiche nella directory delle estensioni, che era utile, ma Mi piacerebbe molto vedere chiarito in modo chiaro e conciso. Immagino lo facciano sempre.

A questo punto mi sembra una classica offuscazione, ma attenzione: hai qualche codice da fare prima che il problema sia di conseguenza.

+0

Mi hai completamente perso verso la fine. – user183037

+2

E io. Sembra che tu abbia perso il punto delle interfacce. Inoltre, non c'è casting qui. – DNA

0

Il punto è identificare il comportamento desiderato/necessario e quindi utilizzare l'interfaccia che fornisce tale comportamento. È il tipo per la tua variabile. Quindi, usa l'implementazione che soddisfa i tuoi altri bisogni: efficienza, ecc. Questo è ciò che crei con "nuovo". Questa dualità è una delle idee principali dietro OOD. Il problema non è particolarmente significativo quando si hanno a che fare con variabili locali, ma raramente fa male seguire sempre buone pratiche di codifica.

Problemi correlati