Pergunta
Estou tendo dificuldade em tentar descobrir isso. Diga que tenho o seguinte código:
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
}
Por que a atribuição resulta em um erro de compilação? O erro é algo como:
Type mismatch: cannot convert from List<capture#4-of ? extends Mammal> to List<Mammal>
De acordo com minha compreensão da covariância, o getMammals()
O método retorna a list
que sempre conterá Mammal
Objetos para que sejam atribuíveis. o que estou perdendo?
Solução
Porque getMammals
poderia retornar um List<Giraffe>
, e se isso fosse convertível para List<Mammal>
Então você seria capaz de adicionar um Zebra
para isso. Você não pode ter permissão para adicionar um Zebra
para uma lista de Giraffe
, você pode?
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
Outras dicas
Bem, infelizmente não funciona assim.
Quando você declara getMammals () para retornar List<? extends Mammal>
Isso significa que pode retornar List<Mammal>
ou List<Giraffe>
mas não List<Animal>
O seu main () deve ficar assim:
public static void main(String[] args) {
List<? extends Mammal> mammals = getMammals();
Mammal mammal = mammals.get(0);
}
EDIT: Em relação à covariância, é isso que geralmente se entende por isso:
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;}
}
Como você pode ver, ele permite sobrecarregar o tipo de retorno de métodos ao substituir o método.