Il meccanismo associato da generici per una variabile di tipo che appare nel suo stesso limite

4

Da Linguaggi di programmazione: principi e paradigmi Di Maurizio Gabbrielli, Simone Martini

The bound mechanism for type variables is fairly sophisticated and flexible. In particular, a type variable can appear in its own bound. We restrict ourselves to a single example of this case, and we refer the reader to the bibliography for a deeper discussion.

The elements of a class are comparable if the class implements the Comparable interface. We want to define a method which, given a list of elements of generic type as its argument, returns the maximum element of this list. What is the signature we can give to this max method? A first attempt is:

public static <T extends Comparable<T>>
T max(List<T> list)

This expresses the fact that the elements of the list must be comparable with elements of the same type. We now try to use max. We have a type Foo which allows us to compare objects:

class Foo implements Comparable<Object>{...}
List<Foo> cf = ....;

We now invoke max(cf): each element in cf (is a Foo and therefore) is comparable with any object, in particular with every Foo. But the compiler signals an error, because Foo does not implement Comparable<Foo>. In reality it is sufficient that Foo is comparable with one of its own supertypes:

public static <T extends Comparable<? super T>>
T max(List<T> list)

Now, under the same conditions as before, Max(cf) is correct because Foo implements Comparable<Object>.

  1. Suppongo che ? super T significhi qualsiasi supertipo di T .

    Poiché Object è un supertipo di T , esegue la seguente firma di max lavoro?

     public static <T extends Comparable<Object>>
     T max(List<T> list)
    

    Se sì, perché non usarlo invece l'ultimo nella citazione?

  2. Questo è un esempio che coinvolge l'interfaccia Comparable . Qual 'é problema generale che possiamo usare il metodo nella citazione per risolvere?
posta Tim 24.10.2016 - 19:17
fonte

1 risposta

3

Se avessimo:

public static <T extends Comparable<Object>>
T max(List<T> list)

Avrebbe funzionato con

class Foo implements Comparable<Object>{...}
List<Foo> cf = ....;

Ma non con

class Bar implements Comparable<Bar>{...}
List<Bar> cf = ....;

La loro prima max firma richiede che T possa essere confrontato con T - quindi non può funzionare su List di Foo s, perché Foo s può essere confrontato con Object . La tua firma max richiede che T possa essere confrontato con Object , quindi non può funzionare su List di Bar s, perché Bar può essere confrontato solo con un altro Bar .

La loro seconda versione max è necessaria per lavorare su List<Foo> e List<Bar> . Dice: " dammi una lista di qualcosa che può comparare con altri oggetti del suo tipo, ma se ha un metodo di confronto più ampio, che accetta anche altri tipi, sarebbe OK - purché possa accettare che sia proprio tipo. ".

Quindi, un elenco di Baz implements Comparable<Foo> è fuori questione, perché, poiché Baz non può essere confrontato con se stesso ( Baz is not a subclass of Foo ').

Fondamentalmente, il problema generale risolto con questo metodo è che qualcosa in un generico può funzionare con una sottoclasse / superclasse del parametro generico, perché tu sei solo upcast da / a esso. Usa ? super T / ? extends T per codificarlo nella firma, in modo che il generico possa essere usato con una più ampia varietà di tipi.

    
risposta data 25.10.2016 - 01:53
fonte