Newsgroup: it.comp.java
Titolo: Domanda "generica" (sui generics :))

Ciao a tutti.
Volevo chiedervi un parere su qual e` il modo piu` elegante per
risolvere il seguente problema.
Supponiamo di avere una classe C parametrica su un tipo T.
class C<T extends Something> {
  private T info;
  ...
  T getInfo() {
    return info;
  }
}
Ora supponiamo di avere una collezione che ospita oggetti di tipo C e
che in questa collezione si voglia utilizzare il campo info degli
oggetti contenuti per fare ricerche:
class CCollection<T extends C> extends HashSet<T> {
  ...
  T findByInfo(Something info) {
    for(T t : this) {
      if(t.getInfo().compareTo(info) == 0) {
        return t;
      }
    }
    return null;
  }
}
Questo codice funziona solo che tira fuori i vari warning riguardo alla
non istanziazione di T rispetto al parametro di tipo necessario alle
classi parametriche di tipo C.
Una soluzione che elimina questo problema e` dichiarare
class CCollection<T extends Something> extends HashSet<C<T>> {
  ...
  C<T> findByInfo(T info) {
    ...
  }
}
A questo punto esplicito il tipo da passare come parametro
all'instanziazione della classe C e posso esplicitamente fare confronti
sul tipo effettivo T del campo info delle classi C<T>. Tuttavia la cosa
e` fuorviante perche` quando si crea una CCollection dichiarandola
CCollection<SomethingSubclass> si potrebbe aver l'impressione di stare
creando delle collezioni di SomethingSubclass invece di
C<SomethingSubclass>. Insomma, non mi piace :)
L'ultima opzione e` quella di esplicitare sia il parametro T che serve
per istanziare le classi C nella collezione, sia il tipo C<T> che sara`
contenuto nella collezione:
class CCollection<T extends Something, S extends C<T>> extends
HashSet<S> {
  ...
  S findByInfo(T info) {
    ...
  }
}
Questa opzione risolve tutti i problemi ma e` pesante da scrivere
perche` ogni volta che devo dichiarare una CCollection devo scrivere
qualcosa come:
CCollection<SomeThingSubclass, CSubclass<SomethingSubclass>>
Un po' ridondante ed anche un po' confusionario.
Non mi vengono in mente altre soluzioni.
La piu` "elegante" mi sembrerebbe la prima (quella che genera i
warning). Ma i warning mi danno fastidio :)
Voi quale scegliereste?
Esiste un modo per rimuovere i warning dalla prima soluzione?
Grazie ed a presto!

 class CCollection<T extends C> extends HashSet<T> {
Uhm... hai detto che questa collezione deve ospitare oggetti di tipo C, 
ma anche C è generico. Per cui mi aspetterei di leggere quale tipo di C 
si debba utilizzare. Tradotto:
class CCollection<T extends C<SomethingOther>> extends HashSet<T>
a occhio dovrebbe andare.
pole
-- 
ammentos - a lightweight persistence framework for JDK5
http://www.sourceforge.net/projects/ammentos
http://ammentos.biobytes.it


No purtroppo non va.
Perche` il compilatore non riesce a risolvere SomeOtherThing.
Quello che hai scritto, in realta`, si concretizza nella mia terza
soluzione dove si esplicita cos'e` SomeOtherThing:
class CCollection<SomeOtherThing extends Something, T extends
C<SomeOtherThing>> extends HashSet<T> {
 ...
}
Ma volevo evitare di appesantire cosi` tanto la dichiarazione.
A presto


 Perche` il compilatore non riesce a risolvere SomeOtherThing.
Beh certo :) Ho messo SomeOtherThing giusto per dire "un qualunque altro 
tipo", intendevo "il tipo generico assegnato a C". Ovvero se usi 
C<String> avrai:
class CCollection<T extends C<String>> extends HashSet<T>



Si, ma questo non e` quello che chiedevo.
Fissando C<String> (o con qualsiasi altro tipo non generico) perdo la
parametricita` proprio su quel tipo, cosa che io volevo :)
In particolare, la CCollection che hai suggerito funziona per C<String>
e derivati. Ma se volessi una CCollection per C<Integer>, ad esempio,
dovrei duplicare il codice creando una nuova classe.
Io, invece, cercavo il modo per scrivere una sola volta una CCollection
parametrica sullo stesso parametro di C in modo "elegante" (come
accennato nel precedente messaggio)
Grazie e ciao.

 parametricita` proprio su quel tipo, cosa che io volevo :)
Ok :) Sorry avevo capito che cercassi proprio questo.
Allora che ne dici di questa?
CCollection<T extends C<? extends Object>> extends HashSet<T>
la puoi utilizzare cosě:
CCollection<C<String>> cc = new CCollection<C<String>>();
e cc.findByInfo() ti restituisce un C<String>
oppure cosě:
CCollection<C<Integer>> cc = new CCollection<C<Integer>>();
e cc.findByInfo() ti restituisce un C<Integer>
Se non va bene nemmeno cosě allora proprio sono io che non mi/ti capisco :P



Bingo :)
Questo risolve il problema
CCollection<T extends C<?>> extends HashSet<T>
addio warnings! :)
Grazie per l'aiuto