2009-07-26 6 views
7

J'ai du mal à comprendre cela. Dire que j'ai le code suivant:Java covariance

class Animal { } 
class Mammal extends Animal { } 
class Giraffe extends Mammal { } 
... 
public static List<? extends Mammal> getMammals() { return ...; } 
... 

public static void main(String[] args) { 
    List<Mammal> mammals = getMammals(); // compilation error 
} 

Pourquoi l'affectation entraîne-t-elle une erreur de compilation? L'erreur est quelque chose comme:

Type mismatch: cannot convert from List<capture#4-of ? extends Mammal> to List<Mammal> 

Selon ma compréhension de covariance, la méthode renvoie un getMammals()list qui contiennent toujours des objets Mammal il devrait donc être cessible. Qu'est-ce que je rate?

Répondre

19

Parce que getMammals pourrait retourner un List<Giraffe>, et si cela était à List<Mammal> alors convertable vous seriez en mesure d'ajouter un Zebra à lui. Vous ne pouvez pas ajouter Zebra à une liste de Giraffe, et vous?

class Zebra extends Mammal { } 

List<Giraffe> giraffes = new List<Giraffe>(); 

List<Mammal> mammals = giraffes; // not allowed 

mammals.add(new Zebra()); // would add a Zebra to a list of Giraffes 
6

Eh bien, cela ne fonctionne malheureusement pas comme ça.

Lorsque vous déclarez getMammals() pour revenir List<? extends Mammal> cela signifie qu'il peut retourner List<Mammal> ou List<Giraffe> mais pas List<Animal>

vôtre main() devrait ressembler à ceci:

public static void main(String[] args) { 
    List<? extends Mammal> mammals = getMammals(); 
    Mammal mammal = mammals.get(0); 
} 

EDIT: En ce qui concerne covariance, c'est ce que l'on entend habituellement par cela:

class Animal { 
    public Animal getAnimal() {return this;} 
} 

class Mammal extends Animal { 
    public Mammal getAnimal() {return this;} 
} 

class Giraffe extends Mammal { 
    public Giraffe getAnimal() {return this;} 
} 

Comme vous pouvez le voir, cela permet de surcharger rn type de méthodes lorsque vous redéfinissez la méthode.

+0

+ 1, mais pourriez-vous expliquer ce que signifie "Liste ou Liste mais pas Liste" ?! : p –

+0

Reformaté pour supprimer la liste confuse «List ou List mais pas List» :-) –

+0

Les génériques étaient traités comme html, échappés –