Perché l'interfaccia ListE viene introdotta anche nella gerarchia delle collezioni? [duplicare]

1

Di seguito è riportato il diagramma, dove, se consideriamo solo le implementazioni di List,

  1. AbstractListmantieneilcomportamentodibasedellalista.PerintrodurrelanuovaimplementazioneclassMyList(diciamo)sipuòereditareAbstractListesovrascrivere(senecessario)imetodirichiesti.EstendendoAbstractList.Inoltre,classMyListstarispettandoilcontrattopercomportarsicomeunelenco.

    classMyListextendsAbstractList{..}
  2. Gliutentipossonoutilizzarelagerarchiadiraccolta,come,

    AbstractListl=newArrayList<String>();l.add("one"); //execute ArrayList's add method
    
  3. Una classe può anche mantenere una relazione di composizione con qualsiasi implementazione di lista (in fase di esecuzione), avendo

    AbstractList l;
    

    come membro, che viene popolato in fase di runtime, con qualsiasi implementazione di lista.

Quindi

Mi piacerebbe capire la ragione chiara, perché viene aggiunto ulteriormente interface List<E> ?

note1: L'intenzione è capire, come usare l'interfaccia. Questa non è una domanda duplicata, perché vengono utilizzate sia la classe astratta che l'interfaccia. Non ho usato la parola "invece di" o "piuttosto"

note2: Non entriamo nei metodi predefiniti di java-8, poiché la gerarchia di raccolta precedente è stata progettata con tutto ciò che è stato fornito fino a java-7

    
posta overexchange 05.07.2015 - 04:16
fonte

3 risposte

7

La tua domanda sembra derivare dall'assunto sbagliato che ogni List è anche una sottoclasse di AbstractList . Mentre AbstractList offre implementazioni di base versatili per molti metodi, ci potrebbero essere dei motivi per non usare questa opzione.

È difficile trovare un esempio quando si cerca solo l'API public , ma ce n'è uno: CopyOnWriteArrayList .

Ne troverai di più una volta compreso che non tutte le implementazioni sono public , ad es. esaminando Collections.unmodifiableList e Collections.synchronizedList , entrambi restituire implementazioni che non ereditano da AbstractList per una buona ragione. Hanno classi base più adatte al loro compito, UnmodifiableList estende UnmodifiableCollection e SynchronizedList estende SynchronizedCollection .

Ci possono essere altri motivi specifici dell'applicazione per non sottoclasse AbstractList , alla fine, la decisione di rendere l'intero Collection -API interface -based è fondamentale e non c'è motivo di fare un'eccezione per List . Non è diverso il motivo per cui dovresti utilizzare l'interfaccia Collection anziché AbstractCollection o l'interfaccia Set anziché AbstractSet ...

Per sapere come usarlo ... Se si tratta di parametri o variabili heap che dovrebbero offrire la massima flessibilità, ovviamente, dovresti sempre usare il tipo meno specifico richiesto per l'operazione, ad es. l'interfaccia List , se è richiesto che il Collection fornito abbia% sem_de List . Come detto, ci sono List tipi che non estendono AbstractList .

Se si tratta di variabili locali all'interno di un codice di implementazione, potresti dichiarare una variabile che corrisponde al tipo di implementazione effettiva, ad es. ArrayList<X> l=new ArrayList<>(); per ridurre il numero di diversi tipi che si verificano in questo codice. Ma ciò implica ancora che non vi è alcun motivo per fare riferimento a AbstractList . L'unico posto in cui un riferimento è a AbstractList è fattibile è nella clausola extends AbstractList ...

    
risposta data 06.07.2015 - 16:01
fonte
6

In entrambi i frammenti di codice, l'uso di AbstractList è sconsigliato. 1 L'utilizzo corretto consiste nel mettere la nuova istanza di lista in una variabile List .

Le classi astratte AbstractList e AbstractSequentialList vengono fornite per la comodità di implementatori (cioè scrittori di librerie) di contenitori list-like, fornendo implementazioni predefinite (*) per alcuni dei metodi di istanza, nel tentativo di ridurre duplicazione del codice.

(*) Esiste un dibattito legittimo in corso su quali sono i modi (i) preferibili, (ii) tollerabili e (iii) scoraggiati di fornire implementazioni predefinite di metodi di istanza nel linguaggio Java. Consulta alcune delle altre domande poste da overexchange per un punto di partenza.

Ogni contenitore di tipo elenco deve implementare l'interfaccia List direttamente o indirettamente, in modo che siano utilizzabili da altre applicazioni in modalità elenco. L'ereditarietà di AbstractList o AbstractSequentialList è facoltativa.

Allo stesso modo, le applicazioni che desiderano accettare un contenitore di tipo elenco devono accettare List . Non dovrebbe richiedere un AbstractList o AbstractSequentialList perché squalifica alcuni contenitori tipo elenco.

Per quanto riguarda la motivazione per nominare l'interfaccia List così com'è, è probabile che 2 la decisione di alcuni influenti padri fondatori di Java che hanno deciso che le interfacce non devono avere decorazioni di denominazione che indicano che sono interfacce (cioè non supportate da eventuali implementazioni concrete). Questa posizione è discutibile, ma rimarrà per sempre con il linguaggio Java.

1 "scoraggiato" è usato come eufemismo per "chiaramente sbagliato".

2 Citazione necessaria. Sentiti libero di modificare questo post per aggiungere il riferimento necessario o per rimuovere questo paragrafo se questo non è corretto.

    
risposta data 05.07.2015 - 04:47
fonte
3

I would like to understand the clear reason, Why additionally interface List is introduced?

In Java, i tipi formano un grafico aciclico diretto, ma le classi formano un albero. In quanto tale, i tipi sono strettamente più flessibili delle classi. Quando si progettano le API, si consiglia di utilizzare i tipi non di classe il più possibile per i parametri e i tipi di reso. E praticamente l'unica scelta in Java per un tipo non di classe è un'interfaccia.

In altre parole, le interfacce sono migliori per gli utenti dei tuoi tipi.

Tuttavia (almeno prima di Java 8), se effettivamente vuoi che questi tipi abbiano un'implementazione, hai bisogno di una classe (possibilmente astratta). Quindi le classi sono migliori per gli implementatori dei tuoi tipi.

Per soddisfare sia gli utenti che gli implementatori, i progettisti dell'API List hanno fornito sia un'interfaccia List sia una classe astratta AbstractList .

Stranamente, oggi con Java 8, le interfacce possono avere cosiddette "implementazioni predefinite", eliminando così la necessità della classe astratta AbstractList . Quindi la tua domanda dovrebbe essere formulata in un altro modo: "Perché è stata introdotta la classe astratta aggiuntiva AbstractList ?" e la risposta sarebbe stata "a causa di ragioni storiche, i vecchi Javas non avevano metodi predefiniti."

    
risposta data 05.07.2015 - 09:22
fonte

Leggi altre domande sui tag