Tipi generici

di il
6 risposte

Tipi generici

Ciao a tutti,ho scritto questa classe:
public class Vettore<T> {
    T[] array;
    public Vettore(int capacità) {
        array=(T[])new Object[capacità]
    }
    //.... altri metodi
}
poi ho in un'altra classe questi metodi:

public static bubbleSort(Comparable[] c) {
    // corpo
}

public static bubbleSort(Vettore<Comparable> v) {
 // corpo
}
dove Comparable è l'interfaccia presente in java.lang

se in un main scrivo:
Vettore<Integer> i=new Vettore<Integer>(5);
// i metodi add() sono di Vettore
i.add(5);
i.add(2);
i.add(3);

bubbleSort(i) // qui ho un errore
in pratica l'errore che mi viene segnalato è che i di tipo Vettore<Integer> non è un Comparable[].
perchè succede questo?
i non è un Vettore<Comparable> visto che Integer implementa Comparable?
perchè bubbleSort chiama il metodo overloaded con parametro Comparable[] c?

6 Risposte

  • Re: Tipi generici

    Guarda bene quello che hai scritto:
    public class Vettore<T> {
        T[] array;
        public Vettore(int capacità) {
            array=(T[])new Object[int capacità]
        }
        //.... altri metodi
    }
    vedi la castronata?
    Che cosa stai castanto? Perche''? Ma se fosse cosi', a che servirebbe <T>?
  • Re: Tipi generici

    In che senso, quel casting serve a creare un array di T,visto che l'inizializzazione esplicita con T non è permessa.
  • Re: Tipi generici

    Il problema è che un Vettore<Integer> non è un Vettore<Comparable>, non lasciarti confondere dai generici.

    Un Vettore<Comparable> può contenere qualunque tipo di oggetto che implementi Comparable (Integer, String, Double, quel che ti pare che implementa Comparable). Supponiamo, quindi, di avere un Vettore<Comparable> di questo tipo:
    
    Vettore<Comparable> v = new Vettore<Comparable>();
    v.add( 5 );   // Ammesso: Integer è Comparable
    v.add( "Ciao" ) ;   // Ammesso: String è Comparable
    v.add( new Date() );   // Ammesso: Date è Comparable
    
    Questo oggetto non contiene SOLO Integer, quindi è diverso da un Vettore<Integer> e non è nemmeno assegnabile (per ovvie ragioni). Quindi, Vettore<Integer> e Vettore<Comparable> sono oggetti completamente differenti.

    Che succederebbe se fossero assegnabili? Bene... io ho un metodo che accetta un Vettore<Comparable> e gli passo un Vettore<Integer>. Chi mi vieta di fare questo?
    
    Vettore<Integer> v = new Vettore<Integer>();
    metodo( v );
    
    ...
    
    public void metodo(Vettore<Comparable> v) {
       v.add("Ciao");
    }
    
    Se io potessi passare il mio vettore di interi ad un metodo che accetta un vettore di Comparable, nessuno mi vieterebbe di "rovinare" il vettore inserendovi delle stringhe... e questo è assolutamente contrario ad ogni logica di type-checking.

    Quello che serve a te è un modo per indicare al compilatore che il tuo metodo accetta un Vettore composto di tipi Comparable. E lo si fa con i bounded wildcard:
    
    public static void bubbleSort(Vettore<? extends Comparable> v) {
       ... // Corpo del metodo
    }
    
    In questo caso, il metodo bubbleSort() accetterà qualunque vettore contenente dei comparable.

    Ciao.
  • Re: Tipi generici

    In realta' un'espressione del tipo:
    Vector<Comparable> v = new Vector<Integer>()
    sarebbe concettualmente valida in un linguaggio che supporta il concetto di covarianza in senso piu' generale di quanto viene fatto correntemente.

    Il concetto di covarianza e' quello che permette di fare un'assegnazione del tipo:
    Oject o = 5
    perche' '5' (un intero) e' un tipo piu' specializzato di 'Object' (tipo base per tutte le tipologie di dati/oggetti). Concettualmente e' sempre possibile passare da un tipo specifico ad un tipo piu' generale. L'operazione contraria, invece, non sempre ha senso. QUando supportata, si parla di controvarianza.

    Certo, ci sono delle conseguenze nel supportare un concetto del genere (appunto, rovinare un Vector<Integer>), e poiche' e' complicato, ci sono pochissimi linguaggi che lo supportano (Haskell se ricordo bene).
  • Re: Tipi generici

    xneo ha scritto:


    in che senso, quel casting serve a creare un array di T,visto che l'inizializzazione esplicita con T non è permessa.
    Infatti, non e' permessa, ma questo, anche se sembra funzionare, in realta e' fittizzio:
    
    import java.lang.reflect.Array;
    
    class V<T>
    {
        T[] v;
    
        V(int l)
        {
             v = (T[])new Object[l];
        }
    
    
        T[] vect()
        {
            return  v;
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
    
            V<Integer> v = new V<Integer>(10);
    
            int i = v.vect()[1]; // badabum!!!!
        }
    }
    
    Invece, quello che si deve utilizzare, e' Array.newInstance(...)
    v = Array.newInstance(T.class, l)
    (nota: il codice cosi' non compila !!)

    Ora il problema e' ricuperare 'T.class'. Questo puo' essere fatto via Reflection sulla classe 'V<T>'.
  • Re: Tipi generici

    Migliorabile ho capito quello che vuoi dire,
    questo pericolo non si otterrebbe se scrivessi anche:
    Integer[] v=(Integer[])Object[10];

    questa cosa credo dipenda dal buon senso del programmatore.

    il mio problema era un altro(e ringrazio leleft).
    in pratica io pensavo che un Vettore<Integer> era anche un Vettore<Comparable>.
Devi accedere o registrarti per scrivere nel forum
6 risposte