little_lakes ha scritto:
Creo la classe astratta Libro e le due figlie Rivista e Giornale
public class Libro {}
public class Giornale extends Libro {}
public class Rivista extends Libro {}
Ma non avevi detto Libro astratto?? Comunque fin qui, di per sé, ok.
little_lakes ha scritto:
Creo poi la classe Catalogo e inserisco il generics <T extends Libro> così che quando andrò a creare una istanza di Catalogo potrò scegliere cosa mettere al suo interno tra Rivista e Giornale dato che entrambe ereditano Libro.
Attenzione a una cosa: il bound
extends Libro permette solo di limitare una parametrizzazione concreta a qualcosa che è o estende Libro.
Quindi si può fare:
Catalogo<Libro> catLibri = new Catalogo<Libro>();
oppure
Catalogo<Giornale> catGiornali = new Catalogo<Giornale>();
oppure
Catalogo<Rivista> catRiviste = new Catalogo<Rivista>();
ma NON ad esempio un Catalogo<String> o un Catalogo<Integer> ecc...
Però, attenzione, Catalogo<Libro> , Catalogo<Giornale> e Catalogo<Rivista> sono 3 tipi differenti e NON in relazione tra di loro. In particolare un Catalogo<Giornale> NON è un sottotipo di Catalogo<Libro> (nonostante Giornale sia un sottotipo di Libro).
E in un Catalogo<Libro> ci puoi mettere sia oggetti Giornale che Rivista, chiaramente.
little_lakes ha scritto:
Ora creo la classe Biblioteca. Ha un ArrayList di cataloghi qualsiasi, nel senso che al suo interno possono esserci sia Catalogo<Rivista> che Catalogo<Giornale>
Usare ArrayList<Catalogo<? extends Libro>> è di per sé corretto per il fine descritto.
Cioè, in un ArrayList del genere puoi in effetti metterci sia un Catalogo<Giornale> che un Catalogo<Rivista> (come anche un Catalogo<Libro>).
Il problema semmai è nella estrazione. Immagina che il ArrayList contenga 2 elementi, un Catalogo<Giornale> e un Catalogo<Rivista>.
Tu puoi "vedere" un elemento solo come Catalogo<? extends Libro>
Catalogo<? extends Libro> primoCat = cataloghi.get(0);
E il problema è che in Catalogo<? extends Libro> NON ci puoi inserire nulla! (a parte un null letterale). Puoi solo estrarre un oggetto come Libro (o al limite super-tipo).
little_lakes ha scritto:
Ho però un problema sul secondo metodo:
The method addLibro(capture#3-of ? extends Libro) in the type Catalogo<capture#3-of ? extends Libro> is not applicable for the arguments (Libro)
Come posso risolvere?
Non risolvi ... non così.
Tu vorresti inserire un oggetto che è-un Libro quindi materialmente l'oggetto potrebbe essere un Giornale o un Rivista (non esattamente Libro perché abstract come volevi). E vorresti metterlo in un Catalogo<? extends Libro> che
non sai che cosa è. Non sai se concretamente era (quando l'hai inserito) un Catalogo<Giornale> o un Catalogo<Rivista>.
Se fosse un Catalogo<Rivista> e tu volessi metterci dentro un Giornale? Ovviamente NOOO. Tutta la teoria dei generics andrebbe a farsi friggere .... e infatti il compilatore te lo proibisce!
Come ho già detto prima, in un Catalogo<? extends Libro> non si può inserire nulla (a parte null letterale).
Il problema di "fondo" (dovuto alla
erasure dei generics) è che quando inserisci un es. Catalogo<Giornale> all'interno del ArrayList<Catalogo<? extends Libro>>, quella parametrizzazione concreta <Giornale> in pratica "si perde". Non c'è più scritto da nessuna parte nel ArrayList che l'elemento a indice es. 2 è un Catalogo<Giornale> !!!