I wildcard sono stati introdotti per offrire una specie di "polimorfismo" anche sui tipi parametrici.Originariamente inviato da Hysoka
è proprio questo quello che non riesco a capire...a cosa servono questi wildcards?
I generics sono stati implementati tramite una tecnica che si chiama "erasure" e per via di questo è stato deciso di rendere i tipi parametrici "invarianti". Un esempio per chiarire: un ArrayList<Number> non è un ArrayList<Object>!! (nonostante Number è un Object).
Se questa cosa fosse permessa, non avendo informazioni sul tipo parametrico a runtime ("erasure"), prova a immaginare cosa potrebbe succedere....codice:ArrayList<Number> numArr = new ArrayList<Number>(); ArrayList<Object> objArr = numArr; // NOOO, errore
Il fatto che i tipi parametrici sono invarianti ovviamente è stato visto come un limite. Ecco quindi che sono stati introdotti i wildcard (che hanno regole molto particolari e complesse).
A questo punto potresti chiederti: posso inserire un String usando objArr?? La risposta è no! Il wildcard indica: "non so di che tipo è". Con l'extends che dice: "ma sicuramente è di un tipo Object o suo sottotipo".codice:ArrayList<Number> numArr = new ArrayList<Number>(); ArrayList<? extends Object> objArr = numArr; // SI
Se non si sa di che tipo è, chiaramente non si può inserire nulla.
Ora potresti chiederti a cosa serve un wildcard. Bene, l'esempio pratico e lampante è nella interfaccia Collection<E> che ha un metodo:
boolean addAll(Collection<? extends E> c)
Se hai una Collection<Number>, puoi aggiungere alla collezione tutti gli elementi in una Collection<Number> ma anche Collection<Integer> o Collection<Double>. Perché è logico. E con il wildcard è possibile.
(piccola nota: complicando un pochino la dichiarazione di addAll si poteva evitare l'uso del wildcard ma con il wildcard è decisamente più chiaro e semplice).

Rispondi quotando