Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
1
Unidade V Unidade V –– HeranHerançça e a e
LigaLigaçção Dinâmicaão Dinâmica
Linguagem de ProgramaLinguagem de Programaçção Ião I
Universidade Federal da Paraíba
Centro de Ciências Exatas e da Natureza
Departamento de Informática
Daniela Coelho Batista Guedes Pereira © 2
Unidade V
Conteúdo abordado:
Herança
Ligação Dinâmica e Polimorfismo
Classes Abstratas
3
Herança
A Herança é a contribuição original do paradigma
de programação orientado a objetos
Fundamentos chave do paradigma OO:
Abstração de Dados
Herança
Ligação Dinâmica
A herança é um relacionamento entre classes
Relacionamento do tipo é um
Classes são derivadas de outras classes, portanto
herdam atributos e métodos dessas classes.
4
Herança
5
Herança
Forma de reutilização de código
Propriedades e métodos são herdados, evitando sua
duplicação em várias classes similares
Forma de generalização/especialização de tipos
Várias classes podem ser generalizadas em uma
classe que concentre todas as características comuns
a todas elas
Uma classe pode ser especializada em várias outras
classes
Pelo menos duas classes participam da herança
6
Herança
Papéis das classes que participam da herança:
Superclasse: classe a partir da qual são herdadas as
propriedades e métodos
Subclasse: classe que herda as propriedades e
métodos da superclasse
Se uma classe herda de outra, então:
Os objetos da subclasse possuem todas as
propriedades de instância declaradas na superclasse
Pode-se enviar para um objeto da subclasse uma
mensagem cuja implementação esteja na superclasse
2
7
Herança
Exemplos de relacionamentos de herança no
mundo real:
Um carro é um veículo
Um gerente é um funcionário
Um homem é um mamífero
Um mamífero é um animal
Na POO a herança não é um relacionamento
entre objetos, mas entre as classes destes
objetos
No mundo real, a herança algumas vezes é uma
relação entre seres (o filho herda dos pais) 8
Herança
Definindo herança na UML:
Quadrado
-lado: int
+draw()
Triangulo
-base: int
-altura:int
+draw()
Circulo
-raio: int
+draw()
Figura
-pos: Ponto
+setPos()
Especialização
Generalização
9
Herança
Declaração de herança em Java:
public class Figura {
private Ponto pos;
public void setPos(Ponto p) { ... }
}
public class Figura {
private Ponto pos;
public void setPos(Ponto p) { ... }
}
public class Quadrado extends Figura {
private int lado;
public void draw() { ... }
}
public class Quadrado extends Figura {
private int lado;
public void draw() { ... }
}
palavra reservada de Java
10
Herança
Declaração de herança em C++:
class Figura {
private:
Ponto pos;
public:
void setPos(Ponto p) { ... }
}
class Figura {
private:
Ponto pos;
public:
void setPos(Ponto p) { ... }
}
class Quadrado:Figura {
private:
int lado;
public:
void draw() { ... }
}
class Quadrado:Figura {
private:
int lado;
public:
void draw() { ... }
}
11
Herança
Declaração de herança em Smalltalk:
classname Figura superclass Object
instance variable names
|pos|
setPos: p
"Implementação de setPos"
classname Figura superclass Object
instance variable names
|pos|
setPos: p
"Implementação de setPos"
classname Quadrado superclass Figura
instance variable names
|lado|
draw
"Implementação de draw"
classname Quadrado superclass Figura
instance variable names
|lado|
draw
"Implementação de draw"
12
Herança
Efeito da herança sobre os objetos da subclasse:
Figura f = new Figura();
Quadrado q = new Quadrado();
Figura f = new Figura();
Quadrado q = new Quadrado();
pos
f q
lado
pos
f.setPos(new Ponto(10,20));
q.setPos(new Ponto(30,40));
q.draw();
f.setPos(new Ponto(10,20));
q.setPos(new Ponto(30,40));
q.draw();
Operações
perfeitamente
válidas
3
13
Herança
Herdando o estado:
Todos os objetos da subclasse terão uma cópia das variáveis
de instância declaradas em todas as suas superclasses
Herdando o comportamento:
Todos os métodos de instância da superclasse também são
métodos dos objetos das suas subclasses
Construtores não são herdados pelas subclasses, mas o
construtor da superclasse tem que ser invocado na subclasse
implicitamente (através do construtor default) ou explicitamente
(através da clausula super).
Ao enviar uma mensagem para um objeto da subclasse, a
busca por um método começa na subclasse e se estende
pelas superclasses
14
Herança
public class Bicycle {
//a classe Bicycle tem três campos
private int cadence;
private int gear;
private int speed;
//a classe Bicycle tem um construtor
public Bicycle(int startCadence,int startSpeed,int startGear){
gear = startGear;
cadence = startCadence;
speed = startSpeed; }
//a classe Bicycle tem quatro métodos
public void setCadence(int newValue) { cadence = newValue; }
public void setGear(int newValue) { gear = newValue; }
public void applyBrake(int decrement) { speed -= decrement; }
public void speedUp(int increment) { speed += increment; }
}
15
Herança
public class MountainBike extends Bicycle {
//a subclasse MountainBike adiciona um campo
private int seatHeight;
//a subclasse MountainBike tem um construtor
public MountainBike(int startHeight, int startCadence,int
startSpeed,int startGear){
super(startCadence, startSpeed, startGear);
seatHeight = startHeight; }
//a subclasse MountainBike adiciona um método
public void setHeight(int newValue) {seatHeight = newValue; }
}
16
Herança
Níveis de acesso a membros de uma classe:
O acesso package ou friendly é obtido quando não se
especifica nenhum dos outros três modificadores de
controle de acesso.
Classe Subclasse Pacote Outros
private
public
protected
package
17
Herança em Java
Observe que:
O encapsulamento private não impede que uma
propriedade ou método seja herdado; entretanto, o
acesso a estes membros é impedido na subclasse
O nível de acesso protected permite que
membros sejam invisíveis a outras classes, mas
sejam visíveis às subclasses e às classes do mesmo
pacote
Java possui uma classe Object que é a raiz da árvore
de classes da linguagem (não tem superclasse)
Java só permite herança simples (apenas uma
superclasse) 18
Herança
Sobrescrita de métodos
Se uma subclasse implementa um método de
instância que já exista na superclasse dizemos que
houve uma sobrescrita de método (override)
Os métodos devem possuir a mesma assinatura
A busca pelo método inicia-se e termina na subclasse
O método sobrescrito pode chamar o método original
da superclasse na sua implementação: super
• Neste caso, se a visibilidade o permitir
Não confunda esse conceito com sobrecarga
4
19
Herança
Sobrescrita de métodos
Se uma subclasse implementa um método de classe
que já exista na superclasse dizemos que houve uma
ocultação do método da superclasse (hiding)
20
Herança: overhiding X hiding
public class Animal {
public static void testClassMethod() {
System.out.println(“Método de classe em Animal.");
}
public void testInstanceMethod() {
System.out.println(“Método de instância em Animal.");
}
}
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println(“Método de classe em Cat."); }
public void testInstanceMethod() {
System.out.println(“Método de instância em Cat."); }
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
Cat.testClassMethod();
myAnimal.testInstanceMethod(); }
}
Método de classe em Animal.
Método de classe em Cat.
Método de instância em Cat.
21
Herança
Exemplo de sobrescrita:
Venda
-data: Date
+getData(): Date
+addProduto(Produto)
+getTotal(): real
Produto
-preço: real
-descriçao: String
+getValor()
+setValor(double)
0..n
VendaPrazo
-juros: int
+getTotal()
VendaVista
-desconto: int
+getTotal()
22
Herança
Implementação de Venda em Java
public class Venda {
private Produto produtos[];
private int numProdutos;
private Date data;
//Calcula o total bruto da conta
public double getTotal() {
double total = 0.0;
for (int i=0; i<numProdutos ;i++) {
total += produtos[i].getPreco();
}
return total;
}
}
public class Venda {
private Produto produtos[];
private int numProdutos;
private Date data;
//Calcula o total bruto da conta
public double getTotal() {
double total = 0.0;
for (int i=0; i<numProdutos ;i++) {
total += produtos[i].getPreco();
}
return total;
}
}
23
Herança
Implementação de VendaPrazo em Java:
A referência super aponta para o objeto corrente, mas
faz a busca pelo método getTotal() começar na
superclasse de VendaPrazo
Sem o super, a chamada seria recursiva!
public class VendaPrazo extends Venda {
private int juros;
public double getTotal() {
return super.getTotal()*(1+juros/100.0);
}
}
public class VendaPrazo extends Venda {
private int juros;
public double getTotal() {
return super.getTotal()*(1+juros/100.0);
}
}
24
Ligação Dinâmica
Uma mensagem só é ligada a um método em
tempo de execução ligação dinâmica
Na ligação estática, a ligação entre a chamada de
um subprograma e sua implementação é estabelecida
em tempo de compilação
Com a herança, não se sabe exatamente qual o
método a ser invocado até que se conheça o tipo
real do objeto (tipo dinâmico).
Durante a compilação só temos o tipo das referências
(tipo estático)
5
25
Ligação Dinâmica
Considere o seguinte código:
public class Caixa {
private Venda vendas[];
private int numVendas;
//Calcula o total do caixa
public double getTotal() {
double total = 0.0;
for (int i=0; i<numVendas ;i++) {
total += vendas[i].getTotal();
}
return total;
}
}
public class Caixa {
private Venda vendas[];
private int numVendas;
//Calcula o total do caixa
public double getTotal() {
double total = 0.0;
for (int i=0; i<numVendas ;i++) {
total += vendas[i].getTotal();
}
return total;
}
}
26
Venda[ ]
Ligação Dinâmica
Ilustração de um objeto Caixa:
vendas
desconto juros
juros
desconto
Caixa
VendaVista VendaPrazo
VendaVista
VendaPrazo
caixa
27
Ligação Dinâmica
Observe o código do getTotal() de Caixa:
public class Caixa {
public double getTotal() {
double total = 0.0;
for (int i=0; i<numVendas ;i++) {
total += vendas[i].getTotal();
}
return total;
}
}
public class Caixa {
public double getTotal() {
double total = 0.0;
for (int i=0; i<numVendas ;i++) {
total += vendas[i].getTotal();
}
return total;
}
} VendaPrazo
-juros: int
+getTotal()
VendaVista
-desconto: int
+getTotal()
Qual getTotal() será chamado aqui?
28
Ligação Dinâmica
A ligação entre a mensagem vendas[i].getTotal() e
o método getTotal() de uma das classes só é
estabelecida em tempo de execução, quando o
tipo do objeto em vendas[i] for conhecido
Venda é o tipo de cada referência do arranjo vendas
VendaVista e VendaPrazo serão os tipos efetivos
dos objetos referenciados pelo arranjo
Exemplo:
Venda v = new VendaVista();
tipo estático tipo dinâmico
29
Polimorfismo
Polimorfismo
Do Grego poly(muitas) + morpho(formas)
Há dois aspectos do polimorfismo
Métodos de mesmo nome são definidos em várias
classes, podendo assumir diferentes implementações
em cada uma dessas
Propriedade pela qual uma variável pode apontar
objetos de diferentes classes em momentos distintos
Estes aspectos são complementares, e trabalham
juntos
30
Polimorfismo
Exemplo do polimorfismo em métodos:
Triangulo
area();area();
Retangulo Hexagono
area();
Poligono
area();
6
31
Polimorfismo
Exemplo de polimorfismo em variáveis:
Uma variável do tipo Poligono pode assumir a forma
de Poligono, Triangulo, Retangulo, etc.
Poligono p;
p = new Poligono();
...
p = new Triangulo();
...
p = new Retangulo();
Poligono p;
p = new Poligono();
...
p = new Triangulo();
...
p = new Retangulo();
32
Exemplo de uso de Polimorfismo
Área de um arranjo de polígonos:
double areaTotal() {
double areaTotal = 0;
for (int i = 0; i < MAXPOLIG; ++i) {
if (pol[i] instanceof Poligono)
areaTotal +=
pol[i].areaPoligono();
else if (pol[i] instanceof Triangulo)
areaTotal +=
pol[i].areaTriangulo();
double areaTotal() {
double areaTotal = 0;
for (int i = 0; i < MAXPOLIG; ++i) {
if (pol[i] instanceof Poligono)
areaTotal +=
pol[i].areaPoligono();
else if (pol[i] instanceof Triangulo)
areaTotal +=
pol[i].areaTriangulo(); continua
33
Exemplo de uso de Polimorfismo
Área total sem polimorfismo:
else if (pol[i] instanceof Retangulo)
areaTotal +=
pol[i].areaRetangulo();
else if (pol[i] instanceof Hexagono)
areaTotal +=
pol[i].areaHexagono();
return areaTotal;
}
else if (pol[i] instanceof Retangulo)
areaTotal +=
pol[i].areaRetangulo();
else if (pol[i] instanceof Hexagono)
areaTotal +=
pol[i].areaHexagono();
return areaTotal;
}
34
Exemplo de uso de Polimorfismo
Área total com polimorfismo
Rápido, enxuto e fácil de entender
O acréscimo de uma nova subclasse de Poligono não
altera nenhuma linha do código acima!
double areaTotal() {
double areaTotal = 0;
for (int i = 0; i < MAXPOLIG; ++I)
areaTotal += poligono[i].area();
return areaTotal;
}
double areaTotal() {
double areaTotal = 0;
for (int i = 0; i < MAXPOLIG; ++I)
areaTotal += poligono[i].area();
return areaTotal;
}
35
Benefícios do polimorfismo
Legibilidade do código
O mesmo nome para a mesma operação (método)
facilita o aprendizado e melhora a legibilidade
Código de menor tamanho
Código mais claro, enxuto e elegante.
Flexibilidade
Pode-se incluir novas classes sem alterar o código
que a manipulará
O polimorfismo é implementado com o uso
da ligação dinâmica
36
Classes abstratas
Pode-se implementar classes que definem
comportamentos “genéricos”
A essência da superclasse é definida e pode ser
parcialmente implementada
Detalhes são definidos em subclasses especializadas
Em geral, não podem ser instanciadas
Em Java:
Declara-se a classe com abstract
7
37
Classes abstratas
Conta
String num;
double saldo;
credito();
debito();
saldo(){..}
getNum(){..}
Poupanca
double taxa;
credito(){..}
debito(){..}
rendeJuros(){..}
ContaEspecial
int limite;
credito(){..}
debito(){..}
ContaBonus
int bonus;
credito(){..}
debito(){..}
38
Classes abstratas
Quando declarar uma classe abstract?
Quando a classe representar um conceito abstrato e
não fizer sentido instanciá-la
Quando a classe for apenas um ponto de
concentração para propriedades e métodos comuns a
várias subclasses
Quando a classe possuir pelo menos um método
abstrato, deve ser obrigatoriamente abstrata
Classes abstratas reforçam uma decisão de projeto
39
Classes abstratas
ContaEspecial
Poupanca
ContaBonus
Conta
40
Classes abstratas
Exemplo:
public abstract class Conta {
private String num;
private double saldo;
}
public abstract class Conta {
private String num;
private double saldo;
}
public class Poupanca extends Conta {
//...
}
public class Poupanca extends Conta {
//...
}
public class ContaEspecial extends Conta {
//...
}
public class ContaEspecial extends Conta {
//...
}
Não produz
instâncias
41
Classes abstratas
Método abstrato:
Método definido numa classe abstrata e sem
implementação
Sintaxe e semântica:
O método é identificado com a palavra abstract
Apenas a assinatura é declarada na classe abstrata
Todas as subclasses concretas devem implementá-lo
obrigatoriamente
Usado para forçar as subclasses a terem um
determinado comportamento
42
Classes abstratas
Exemplo de métodos abstratos:
public abstract class Figura {
public abstract void desenha();
public abstract double area();
}
public abstract class Figura {
public abstract void desenha();
public abstract double area();
}
public class Quadrado extends Figura {
public void desenha() {...}
public double area() {...}
}
public class Quadrado extends Figura {
public void desenha() {...}
public double area() {...}
}
8
43
Classes e métodos finais em Java
Uma classe pode ser final em Java
Não pode possuir subclasses
Razões para definir classes finais:
Segurança da aplicação (definição de classes
imutáveis)
Decisão de projeto
Um método pode ser final também
Não pode ser sobrescrito nas subclasses
O corpo do método é substituído em todos os pontos
de uso (chamadas inline)
Métodos private são implicitamente final
44
Classes e métodos finais em Java
Uso de final em métodos:
class Exemplo {
private int a;
public final void setA(int a) {
this.a = a;
}
}
class Teste {
private static void metodoTeste(Exemplo ex) {
ex.setA(5);
}
}
45
Classes e métodos finais em Java
Uso de final em métodos:
class Exemplo {
private int a;
public final void setA(int a) {
this.a = a;
}
}
class Teste {
private static void metodoTeste(Exemplo ex) {
ex.a = 5;
}
}
O compilador otimiza o código nas
chamadas a métodos final