Generics
Generics
POO
1
O que são
●
Tipos genéricos
●
São uma forma de definir e utilizar classes de forma genérica
●
Dá flexibilidade ao código
●
Evita o uso exagerado de casting
2
Exemplo
●
Vamos supor que você queira implementar a estrutura de uma
pilha (push, pop, isEmpty) usando um array.
3
Pilha implementada
public class PilhaInt{ public int pop(){
int v[];
int topo; int b = v[topo];
topo--;
public PilhaInt(){
return b;
v = new int[100]; }
topo = -1;
}
4
Exemplo
●
Vamos supor que você queira implementar a estrutura de uma
pilha (push, pop, isEmpty) usando um array.
●
Queremos ter pilhas para diferentes tipos de dados.
●
Por exemplo:
– uma pilha para Integer
– uma pilha para String
– uma pilha para Dado
5
Exemplo
●
Vamos supor que você queira implementar a estrutura de uma
pilha (push, pop, isEmpty) usando um array.
●
Queremos ter pilhas para diferentes tipos de dados.
●
Por exemplo:
– uma pilha para Integer Solução:
– uma pilha para String Implementar uma pilha que se
– uma pilha para Dado possa colocar qualquer tipo
de objeto
6
Pilha genérica
public class Pilha {
// qualquer objeto pode ser colocado
Object v[];
int topo;
//construtor
public Pilha() {
v = new Object[100];
topo = -1;
}
7
Pilha genérica
public void push(Object b) {
v[topo+1] = b;
topo++;
}
8
Usando a pilha genérica
9
Usando a pilha genérica
p.push(d1);
p.push(new Integer(10));
p.push(d2);
d1 = (Dado) p.pop();
d2 = (Dado) p.pop();
10
Usando a pilha genérica
p.push(d1);
p.push(new Integer(10));
p.push(d2);
d1 = (Dado) p.pop();
d2 = (Dado) p.pop();
11
Usando a pilha genérica
p.push(d1);
p.push(new Integer(10));
p.push(d2);
d1 = (Dado) p.pop();
d2 = (Dado) p.pop();
13
Usando a pilha genérica
p.push(10); Conversão automática int →
int k = p.pop();Integer
int j = (Integer) p.pop();
14
Usando a pilha genérica
p.push(10); Conversão automática int →
int k = p.pop();Integer
Erro. Conversão Object →
int j = (Integer) p.pop();
int
15
Usando a pilha genérica
p.push(10); Conversão automática int →
int k = p.pop();Integer
Erro. Conversão Object →
int j = (Integer) p.pop();
int
Conversão automática Integer → int
16
Usando a pilha genérica
p.push(10); Conversão automática int →
int k = p.pop();Integer
Erro. Conversão Object →
int j = (Integer) p.pop();
int
Conversão automática Integer → int
boxing unboxing
17
Resumindo
●
A implementação da pilha genérica
– permite utilizar qualquer tipo de objeto;
– pode levar a erros pela má utilização, por exemplo, empilhando
tipos errados
– requer um grande número de castings, o que pode poluir o
programa.
18
Usando generics
●
O uso de generics permite que se defina uma pilha genérica.
●
Qualquer tipo de objeto pode ser colocado nessa pilha.
●
Ao se instanciar a pilha, pode-se dizer qual o tipo de objeto
vai ser empilhado.
19
Pilha genérica II
public class Pilha<T> {
T v[];
int topo;
public Pilha() {
v = (T[]) new Object[100];
topo = -1;
}
20
Pilha genérica II
public class Pilha<T> {
T v[];
int topo;
Indica que um tipo vai
ser usado como
public Pilha() { “parâmetro” na criação
v = (T[]) new Object[100];
do objeto.
topo = -1;
}
21
Pilha genérica II
public class Pilha<T> {
T v[];
int topo;
O array a ser utilizado
tem todos os elementos
public Pilha() { desse tipo.
v = (T[]) new Object[100];
topo = -1;
}
22
Pilha genérica II
public class Pilha<T> {
T v[]; O array a ser utilizado
int topo;
tem todos os elementos
desse tipo.
public Pilha() {
v = (T[]) new Object[100];
topo = -1;
}
Mas é necessário fazer
um casting ao alocar o
array.
23
push e pop?
Como ficam ?
25
push e pop?
public void push(T b) {
v[topo+1] = b;
topo++;
}
26
push e pop?
public void push(T b) {
v[topo+1] = b;
topo++;
}
27
push e pop?
public void push(T b) {
v[topo+1] = b;
topo++;
}
public T pop() {
T b = v[topo];
topo--;
return b;
}
28
Usando a pilha genérica II
Pilha<Dado> p = new Pilha<Dado>();
Dado d1 = new Dado(),
d2 = new Dado();
p.push(d1);
p.push(d2);
d1 = p.pop();
d2 = p.pop();
29
Usando a pilha genérica II
Pilha<Integer> p2 = new Pilha<Integer>();
p2.push(10);
p2.push(15);
int k = p2.pop();
30
Usando a pilha genérica II
Pilha<Integer> p2 = new Pilha<Integer>();
p2.push(10);
p2.push(15);
int k = p2.pop();
31
Usando a pilha genérica II
Pilha<Integer> p2 = new Pilha<Integer>();
p2.push(10);
p2.push(15);
int k = p2.pop();
d1 = new Dado();
p2.push(d1); ERRO!!!!
32
Totalmente genérica
●
Mesmo definindo a pilha usando tipo genérico, é possível criar
uma pilha totalmente genérica
●
Ou seja, uma pilha que aceite qualquer tipo de objetos
●
Todos objetos misturados
●
Basta não definir o tipo a ser usado
33
Totalmente genérica
Pilha p3 = new Pilha();
p3.push(10);
p3.push(d1);
p3.push("Genérico");
int j = (Integer) p3.pop();
34
Totalmente genérica
Pilha p3 = new Pilha();
p3.push(10);
p3.push(d1);
p3.push("Genérico");
int j = (Integer) p3.pop();
35
Restrições de tipo
●
Ao declarar a classe genérica é possível restringir o tipo a ser
usado
●
Por exemplo, queremos criar uma pilha em que os elementos
tem que ser uma conta bancária.
ContaBancaria
ContaEspecial ContaPoupanca
PoupancaSimple PoupancaOuro
36
Restrições de tipo
public class PilhaConta<T extends ContaBancaria> {
T v[];
int topo;
public PilhaConta() {
v = (T[]) new ContaBancaria[100];
topo = -1;
}
37
Restrições de tipo
public class PilhaConta<T extends ContaBancaria> {
T v[];
int topo;
public PilhaConta() {
v = (T[]) new ContaBancaria[100];
topo = -1;
}
38
Restrições de tipo – usando
PilhaConta<ContaBancaria> p =
new PilhaConta<ContaBancaria>();
39
Restrições – usando
Dado d1 = new Dado(), d2 = new Dado();
p.push(d1);
p.push(d2);
d1 = p.pop(); Todos esses comandos
d2 = p.pop(); Vão produzir erros.
O tipo dos dados
Não é aceito.
40
Restrições – usando
PilhaConta p3 = new PilhaConta();
p3.push(10);
p3.push(d1);
p3.push("Genérico");Todos esses comandos
Vão produzir erros.
O tipo dos dados
Mesmo que p3 seja Não é aceito.
instanciado
sem tipo definido
41
Uso extensivo
●
Muitos tipos em Java usam o conceito de Generics
42
Vector<E>
●
The Vector class implements a growable array of objects. Like
an array, it contains components that can be accessed using an
integer index. However, the size of a Vector can grow or shrink
as needed to accommodate adding and removing items after
the Vector has been created.
●
Vector<Integer> v = new Vector<Integer>();
v.add(100);
v.add(-1000);
int k = v.elementAt(0);
43
Subclasses
44
Subclasses
45
Exercício
●
Um dicionário é uma estrutura onde os elementos são armazenados sob uma
chave. Por exemplo, podemos armazenar os dados sobre um automóvel usando
como chave a placa. Para recuperar os dados do automóvel basta informar a placa
(não a posição onde os dados foram armazenados)
●
Usando dois arrays, crie uma classe Dicionario onde tanto a chave como o valor
tem seu tipo definido por parâmetros de tipo
●
Imagine que as seguintes operações devem estar disponíveis:
– add(K chave, V valor) - adiciona à chave K o valor V
– V get(K chave) - retorna o valor associado à chave K (se não encontrar, retorna null)
– boolean contains(K chave) – verifica se a chave está presente
– boolean containsValue(V valor) – verifica se o valor está presente
46