segunda-feira, 30 de setembro de 2013

Tipos Genéricos (Generic Types)

Vamos imaginar que precisamos criar uma classe chamada Celular, mas nós não sabemos qual tipo de celular que iremos ter por que afinal existem vários. Ele pode ser de um chip, dois, três ou quatro chips, ser touch ou não e por aí vai. Então vamos criar as classes.

public class CelularUmChip {

    private String marca;
    private int numeroChip1;
   
    public CelularUmChip(String marca, int numeroChip1, 
            boolean ehTouch) {
        this.marca = marca;
        this.numeroChip1 = numeroChip1;
        this.ehTouch = ehTouch;
      
    }    
}

class CelularDoisChips {

    private String marca;
    private int numeroChip1, numeroChip2;    

    public CelularDoisChips(String marca,int numeroChip1, 
            int numeroChip2) {
        this.marca = marca;
        this.numeroChip1 = numeroChip1;
        this.numeroChip2 = numeroChip2;
    }
}

Deu de ver que o código vai ficar repetido né? É aí que utilizamos os Generics. Porém os Generics só vieram há ser implementados na versão 1.5 do Java, até então era necessário pegar os tipos como Object e fazer casting para qual o tipo desejado.
A classe Celular ficaria assim:
public class Celular{
 private Object cellphone;

 public Celular(Object cellphone){
  this.cellphone = cellphone;
 }
 
 public Object getCellphone(){
  return cellphone;
 }
}

E no Main seria necessário fazer o casting como representado no código abaixo.

public class Main{
 public static void main(String[] args){
  Celular c = new Celular(new CelularUmChip("Motorola", 81909090));
  
  CelularUmChip c1 = (CelularUmChip)c.getCellphone();
 }
}

Programando desta maneira seria muito fácil ocorrer erros de Casting, como o clássico "ClassCastException", que dispara quando estamos instanciando a classe errada.

Mas a partir do Java 1.5 já se pode usar os Generics. O que ele faz é instanciar uma classe para que ela receba qualquer tipo de classe ou qualquer tipo primitivo, como int, double e etc. Para instanciar uma classe Generics basta colocar ao lado do nome um <T>, assim já estamos dizendo ao compilador que ele irá receber tal classe quando estiver em compilação. O que vai entre <> não se limita somente ao “T”, há outros placeholders:


E – Element

K – Key

N – Number

T – Type

V – Value

Os Generics permitem o uso de mais de um placeholder no mesmo <>, como por exemplo:
Example <T, N, V>
Vamos refazer nosso código agora utilizando Generics.

public class Celular<T>{

    private T cellphone;

    public Celular(T cellphone) {
        this.cellphone = cellphone;
    }    

    public T getCellphone() {
        return cellphone;
    }    
}
Agora nossa classe Celular vai poder receber qualquer uma das outras que foram declaradas antes.
public class Main {
    public static void main(String[] args) {
        
      Celular<CelularUmChip> c = new Celular(new CelularUmChip("Motorola", 
              81909090));
      
        Celular<CelularDoisChips> c2 = new Celular(new CelularDoisChips("Nokia",
                90909090, 99999090));
    }
}

Referência:

Java Efetivo do Joshua Block, Arquiteto de Software na Google
Site Tiexpert, post do Denys William Xavier
Site Plugmaster, post do Dayvid Lima.

Nenhum comentário:

Postar um comentário