2013-08-20 16 views
23

Ho visto il codice come questo molte volte:Motivo per - Elenco lista = new ArrayList();

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

perché la gente prende il genitore di ArrayList (e le altre classi) al posto del tipo di oggetto generato?

Richiede prestazioni inferiori? O perché qualcuno dovrebbe farlo?

+9

Che cosa è con la fissazione sulla "performance"? Il 90% delle volte, si tratta dell'aspetto * meno importante * del codice di scrittura! –

+2

http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface – kiheru

+0

Puoi anche dare un'occhiata a questo: http://stackoverflow.com/questions/ 17459553/why-do-some-people-use-the-list-base-class-to-instantiate-a-new-arraylist – Marc

risposta

36

Quando qualcuno scrive codice come questo, lui/lei sta cercando di seguire un principio di progettazione OO di base che dice -

programma a un'interfaccia, non ad una concreta attuazione

devo ha spiegato questo principio in one of my blog posts. Guarda nella sezione Class Inheritance VS Interface Inheritance.

Per riepilogare il post, quando si utilizza un riferimento di un tipo genitore per fare riferimento a un'istanza di un sottotipo, si ottiene molta flessibilità. Ad esempio, se in futuro avessi bisogno di cambiare l'implementazione del sottotipo, sarai in grado di farlo facilmente, senza modificare gran parte del tuo codice.

Si consideri il seguente metodo -

public void DoSomeStuff(Super s) { 
    s.someMethod(); 
} 

e una chiamata a questo metodo -

DoSomeStuff(new Sub()); 

ora, se mai hai bisogno di cambiare la logica interna someMethod, si può facilmente farlo dichiarando un nuovo sottotipo di Super, ad esempio NewSubType e modifica della logica all'interno di tale implementazione. In questo modo, non dovrai mai toccare altri codici esistenti che utilizzano quel metodo.Sarà ancora in grado di utilizzare il metodo di DoSomeStuff nel seguente modo -

DoSomeStuff(new NewSubType()); 

Avevi dichiarato il parametro di DoSomeStuff essere di Sub, si sarebbe poi dovuto cambiare la sua attuazione troppo -

DoSomeStuff(NewSubType s) { 
    s.someMethod(); 
} 

e può anche incatenare/bolla in molti altri luoghi.

In termini di esempio di raccolta, questo consente di modificare l'implementazione dell'elenco a cui una variabile punta senza problemi. È possibile utilizzare facilmente un LinkedList al posto di un ArrayList.

+2

"Il programma per un'interfaccia, non per un'implementazione concreta" è un buon consiglio. Tuttavia, non è davvero un argomento da fare 'Elenco list = new ArrayList ();' perché a) questo codice è ancora legato a ArrayList a causa del costruttore e b) riguarda più la progettazione dell'API e non l'implementazione privata. È una delle cose java che impari dall'inizio che non è veramente giustificata. Spesso l'implementazione offre alcune sottigliezze che non vedrai mai se insisti a utilizzare l'interfaccia. La risposta è ancora buona, ovviamente. (+1) – atamanroman

+1

MA, la sua argomentazione è ancora valida. È possibile scambiare funzionalità modificando l'argomento. Questo supporta molte caratteristiche del codice, come l'iniezione di dipendenza, l'accoppiamento lento e la sostituibilità. – christopher

+0

@atamanroman: una conseguenza di questo principio ti incoraggia a fare riferimento alle istanze concrete in termini di loro _interfacce_. Questo è il motivo per cui penso che sia rilevante qui. –

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

In collezione quadro List è un'interfaccia mentre ArrayList è la realizzazione. Il motivo principale per farlo è quello di disaccoppiare il tuo codice da uno specifico implementation dell'interfaccia anche questo sarà utile nel caso in cui si desideri passare a qualche altra implementazione di List in futuro.

11

significa che è possibile scambiare il tipo di list in qualsiasi momento con qualsiasi cosa che implementa l'interfaccia List, invece di creare un modello rigido che può utilizzare solo ArrayList. Per esempio:

private List<String> list; 

public SomeConstructor() 
{ 
    // At this point, you can make it any type of object you want. 
    list = new ArrayList<String>(); 
    list = new LinkedList<String>(); 
    list = new AttributeList<String>(); 
} 

Questo sarà abstract il codice che utilizza l'oggetto list, lontano dai dettagli come quello che tipo di oggetto esatto list è. Tutto quello che deve sapere è che ha il metodo add ecc. Si chiama Loose Coupling.

3

Poiché un metodo non deve sapere quale elenco-implementazione si utilizza.

Un metodo ha solo bisogno di sapere che è una lista.

Il metodo può ancora essere utilizzato.

Programmare sempre un'interfaccia, non un'implementazione concreta. (In questo caso Elenco)

3

In genere si preferisce lavorare con la classe di interfaccia (List in questo caso) in modo che qualsiasi implementazione di List possa essere sostituita in seguito con il minimo sforzo se i requisiti cambiano.

Sebbene ArrayList supporti probabilmente alcuni metodi che non sono nell'interfaccia List, questa dichiarazione chiarisce che quei metodi aggiuntivi non sono rilevanti in quel caso.

8

quando si scrive:

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

poi si è sicuri userete solo la funzionalità del dell'interfacciaList.
(ArrayList strumenti List, quindi List è più flessibile). In questo modo, è possibile modificare lo ArrayList in altri tipi in futuro (ad esempio LinkedList ..).

5

per sistemare le cose:

Per una maggiore flessibilità si avvia l'interfaccia List:

Quindi, se non avete bisogno di tutto ArrayList uso List solo.

È possibile scrivere qualcosa come: List<String> = Arrays.asList("aa", "bb","cc").

Di sicuro, meno funzionalità possono aiutare le prestazioni. Come saprai Se vuoi usare l'applicazione multithread, usa invece Vector ma questo peggiorerà le tue prestazioni.

enter image description here

ha portato da here

+1

Source pleace :) –

+2

http://www.wilsonmar.com/1arrays.htm –

+0

@Maxim Shoustin: buona immagine! Questo significa che dovrei prendere "AbstractMap" come riferimento per tutti gli oggetti della collezione di mappe? – codepleb

Problemi correlati