Tipici generici
- Sono un modello di programmazione che permette di definire, con una sola dichiarazione, un intero insieme di metodi o di classi
- E’ un meccanismo molto potente
- Da usare con consapevolezza
Ex.
public class Valore<T> //definisce un tipo generico della classe
{
private final T val; //usa il tipo generuci della classe
public Valore(T val) {this.val = val;}//usa il tipo generuci della classe
public T get() {return val;}//usa il tipo generuci della classe
@Override
public String toString(){return "" + val;}
public String toType(){return val.getClass().getName();}
}
- Per definire un tipo generico della classe, si utilizza la sintassi a parentesi angolari dopo il nome della classe con il tipo generico da utilizzare
- Da quel punto, si utilizza il tipo generico come un qualsiasi altro tipo di classe
Istanziare la classe generica
public static void main (String[] args)
{
Valore <Integer> i = new Valore <> (42);
Valore <String> s = new Valore <> ("ciao");
Valore <Valore<String>> v = new Valore <> (s);
System.out.println(i.get() + ":" + i.getType());
System.out.println(s.get() + ":" + s.getType());
System.out.println(v.get() + ":" + v.getType());
}
L’output sarà:
42: java.lang.Integer
ciao: java.lang.String
ciao: Valore
Classe Grafo
- Il tipo del vertice può essere qualsiasi
- Utilizzare Object fa perdere ogni informazione sul tipo del vertice e costringerebbe a continui downcast
public class Grafo <V>
{
private Set <V> vertici;
public void addVertex (V v) {/*...*/}
public void getVertex (String id)
{
for (V v :vertici)
if (V.toString().equals(id)) return v;
return null;
}
}
Coppia di elementi di tipo generico
public class Coppia <T>
{
private T a,b;
public Coppia (T a, T b)
{
this.a = a;
this.b = b:
}
public T getPrimo() {return a;}
public T getSecondo() {return b;}
}
Specificare più tipi generici di classe
public class Coppia <T>
{
private T a;
private S b;
public Coppia (T a, S b)
{
this.a = a;
this.b = b:
}
public T getPrimo() {return a;}
public S getSecondo() {return b;}
}
- Per convenzione i tipi generici sono chiamati con le lettere T, S, ecc. (E nel caso in cui siano elementi di una collection)
I generici funzionano solo con i tipi derivati
Warning
Non è possibile utilizzare tipi primitivi, ad es.
int
,double
,char
, ecc.
Estendere le classi generiche
- Ovviamente è possibile estendere le classi generiche per creare classi più specifiche
- Ad esempio, una classe Orario può estendere la classe Coppia:
public class Orario extends Coppia <Integer, Integer>
{
public Orario (Integer a, Integer b)
{
super (a, b);
}
}
Le interfacce Comparable e Comparator sono generiche
public interface Comparable <T>
{
int compareTo (T o);
}
public interface Comparator <T>
{
int compare (T o1, T o2);
}
Ex. Estendere un’interfaccia generica con vincolo di compatibilità sul tipo generico
public interface MinMAx <T extends Comparable<T>>
{
T min();
T max ();
}
public class MyClass <T extends Comparable <T>> implements MinMAx<T>
{
//...
}
Definire un metodo generico
- Per definire un metodo generico con il proprio tipo generico è necessario anteporre il tipo generico tra parentesi angolari al tipo di ritono:
static public <T> void esamina(ArrayList <T> lista)
{
for (T o: lista)
System.out.printlm(o.toString());
}
Usare <?> per prendere in input un oggetto di una classe con qualsiasi tipo parametrico
- Nel caso in cui non sia necessario conoscere il tipo parametrico, si può utilizzare <?>
public class Punto <T extends Number>
{
private T x;
private T y;
public Punto (T x, T y) {this.x = x; this.y = y;}
@Override
public String toString() {return "("+x+";"+y+")";}
public static void main (String[] args)
{
Punto <?> p = new Punto <Integer> (10, 42);
System.out.println(p);
p = new Punto <Double> (11.0, 43.5);
System.out.println(p);
}
}