Salve!Salve! Mais uma semana e estou aqui com mais uma série Revisão SCJP. Conforme falei na semana passada, hoje o assunto é: polimorfismo e genéricos onde veremos como eles trabalham juntos e as diferenças em relação ao uso de polimorfismo com array sendo assim é importante você programador Java saber essas diferenças. Somente um detalhe não esquecer que genéricos está apenas a partir do Java 1.5.
Aproveitando, venho informá-los que essa será a ultima coluna da serie Revisão SCJP, na próxima coluna abordarei outros assuntos, mas não precisa fazer essa cara de triste por que a série revisão SCJP voltará de vez em quando basta acompanhar o blog! O motivo é para não ficarmos abordando um único assunto.
Let’s go fight!
Pré-Requisito
– Instalação Java 1.5/superior
– Revisão SCJP Genérico/Generics
Summary
This article presents as use polymorphism and generics. The use polymorphism with generics there is one big different when use polymorphism and array. You cannot create one collection as below:
List<Animal> l = new ArrayList<Dog>();
Same that Dog extends Animal you cannot do this in collections. Because is permit only create collection of same type. However, you can add one object of other type as long as this object extends the class of the type of your collection. See below:
class Animal{}
class Dog extends Animal{}
ArrayList<Animal> la = new ArrayList<Animal>();
la.add(new Animal());
la.add(new Dog());
This code compiles and execute because you have one collection of the same type and add one object that extends the type of collection. Is very important that you have attention with question about polymorphism and generics in the exam because they can to get you confuse. In the end this article there is one link for download of the one list with several example of generics and polymorphism do download this list, analysis the code and after test each example.
Polimorfismo e Genéricos
Ao usar polimorfismo com genéricos é importante ter bastante atenção e “esquecer” temporariamente a regra que é aplicada a um Array. Por exemplo:
Posso ter um Animal[] array, que pode aceitar qualquer tipo ou subtipo de Animal, mas em Conjuntos a coisa é diferente isso não funciona. Veja:
import java.util.ArrayList;
import java.util.List;
class Animal{}
class Dog extends Animal{}
class Poli{
public static void main(String agrs[]){
List<Animal> l = new ArrayList<Dog>();
l.add(new Animal());
l.add(new Dog());
}}
Esse código não compila. Mas por quê?
Por que você está tentando criar um conjunto que aceita tipos diferentes onde deveria ser de um único tipo. É normal você achar que deveria compilar já que Dog extends Animal, caso isso fosse um array de Animal não haveria problema algum mais quando se trata de conjuntos o polimorfismo opera diferente.
Eu costumo dar um exemplo bem pratico veja:
“Se você compra uma caixa de maçã(É-UM Fruta) e levar berinjela(É-UM Fruta) dentro dela, será que você ficaria furioso quando abrisse a caixa? Então o compilador(feirante) ele evitar esse transtorno (ao cliente) permitindo que dentro da caixa de maça fique apenas maçã, mais nenhuma fruta.”
import java.util.ArrayList;
import java.util.List;
class Animal{}
class Dog extends Animal{}
class Poli{
public static void main(String agrs[]){
Poli p = new Poli();
ArrayList<Animal> la = new ArrayList<Animal> ();
la.add(new Animal());
la.add(new Dog()); //aceita porque Dog extends Animal
}}
Coringa <?>
O uso do coringa permite receber qualquer tipo. Quando usa o coringa e extends estamos dizendo que é permitido receber qualquer class que é subtipo daquela class ou uma interface que implementa aquela classe. Mas você não pode adicionar nada ao conjunto. Veja o que não compila:
import java.util.*;
class Carta{}
class Coringa extends Carta{}
class Jogo{
public void cha(List<? extends Carta> car){
car.add(new Carta()); }
public static void main(String [] agrs){
Jogo j = new Jogo();
List<Carta> list = new ArrayList<Carta>();
list.add(new Carta());
j.cha(list);
}}
Não compila porque usei < ? > sendo assim estou dizendo ao compilador que pode receber um conjunto de qualquer subtipo, porém JAMAIS adicioná-lo ao conjunto, nem que seja do mesmo tipo.
Basta alterar essa parte do código para compilar veja:
public void cha(List<? extends Carta> car){
/* observe que não foi adicionado nada a minha lista*/
<? super tipo>
Como temos o extends temos também uma palavra chave super para a notação <?> o qual permite que você adicionar ao conjunto apenas o que está acima daquele tipo.
import java.util.*;
class Carnaval{}
class Banda extends Carnaval{}
class Bloco extends Banda{}
class Chi{
public void carna(List<? super Banda> band){
band.add(new Banda());
band.add(new Bloco());}
public static void main(String [] agr){
Chi ch = new Chi();
List<Carnaval> lis = new ArrayList<Carnaval>();
ch.carna(lis);}}
Observe que meu método aceita qualquer tipo acima de Banda, porém não posso passar Bloco porque eu informei que seria super e nao extends a Banda.
Outro o ponto a observar aqui é que meu método aceitou um argumento do tipo diferente.
Está confuso? Experimente fazer essa alteração:
List<Bloco> lis = new ArrayList<Bloco>();
E veja que o código não compila. Já que o método diz que não é permitido receber nada que não for super a Banda.
<?> – Qualquer Tipo: Permite receber qualquer tipo dog, cat, etc. Porém não posso adicionar(add) nada ao conjunto.
import java.util.*;
class QuaCor{
public void ch(List<?> li){//nada de adicionar algo aqui}
public static void main(String agr[]){QuaCor qc = new QuaCor();
List<Integer> li = new ArrayList<Integer>();
List<QuaCor> list = new ArrayList<QuaCor>();
qc.ch(li);
qc.ch(list);}}
Onde não posso usar coringas:
Na criação dos objetos: List<?> f = new ArrayList<? extends Animal>();
Usar coringas ? apenas: Argumentos ,variáveis e tipos de retornos.
List<? extends Animal> li = new ArrayList<Dog>();
ArrayList<?> list = new ArrayList();
ArrayList<? extends Girafa> g = new ArrayList<Gir>();
//não posso add nada aqui g.add(new Gir()); não compila
<Object>(aceita apenas Object) é diferente de <?> (aceita qualquer coisa).
Quando você usa <?> pode receber qualquer tipo mais quando usa Object pode receber apenas Object se usar <? extends Object> pode ser qualquer tipo: Dog, Cat, Integer. Porém sem adicionar ao conjunto.
Bom pessoal! Espero que tenha gostado da coluna e aprendido um pouco como funciona o polimorfismo com genéricos, no inicio acontece uma pequena revolução no cérebro já que com array o uso do polimorfismo é bem mais fácil. Mas com genéricos não é difícil a questão é se acostumar e ficar atento as regras e lembrar que o segredo de genéricos está no tipo do conjunto. No link abaixo deixei uma lista de classes para você ficar ligado nas pegadinhas para o exame e erros que você pode cometer ao desenvolver uma aplicação usando genéricos e polimorfismo.
Um abraço e até a próxima!
Download – lista de classes
Um comentário em “Série SCJP:Polimorfismo e Genéricos”