• Nenhum resultado encontrado

Programação Orientada a Objetos C ++ 4 Herança e Polimorfismo

N/A
N/A
Protected

Academic year: 2021

Share "Programação Orientada a Objetos C ++ 4 Herança e Polimorfismo"

Copied!
84
0
0

Texto

(1)

Departamento de Informática Prof. Anselmo C. de Paiva

Programação Orientada a Objetos

C

++

4 – Herança e Polimorfismo

Herança

• Como vimos anteriormente, classes podem ser compostas em hierarquias, através do uso de

herança.

• Quando uma classe herda de outra, diz-se que ela a estende ou a especializa, ou os dois. • Herança implica tanto herança de interface

(2)

Número Saldo 21.342-7 875,32 Crédito Débito

Objeto Poupança

R. Juros Número Saldo 21.342-7 875,32 Crédito Débito

Estados do Objeto Poupança

Número Saldo 21.342-7 895,32 Número Saldo 21.342-7 875,32 creditar(20) R. Juros R. Juros Creditar Creditar Debitar Debitar

(3)

Número Saldo

21.342-7 875,32

Débito

Estados do Objeto Poupança

Número Saldo 21.342-7 884,07 Número Saldo 21.342-7 875,32 Creditar Debitar R. Juros(0.01) R. Juros R. Juros Creditar Debitar Debitar

Classe de Poupanças: Assinatura

public class PoupancaD {

public PoupancaD (String n) {}

public void creditar(double valor) {}

public void debitar(double valor) {}

public String getNumero() {}

public double getSaldo() {}

public void renderJuros(double taxa) {}

(4)

Classe de Poupanças: Descrição

public class PoupancaD {

private String numero;

private double saldo;

public void creditar (double valor) {

saldo = saldo + valor; } // ...

public void renderJuros(double taxa) {

this.creditar(saldo * taxa); }

}

Classe de Bancos: Assinatura

public class BancoD {

public BancoD() {}

public void cadastrarConta(Conta c) {}

public void cadastrarPoupanca(PoupancaD p) {}

public void creditarConta(String numero,

double valor) {}

public void creditarPoupanca(String numero,

double valor) {}

// ... }

(5)

Classe de Bancos: Descrição

public class BancoD { private Conta[] contas;

private PoupancaD[] poupancas; private int indiceP, indiceC;

public void cadastrarConta(Conta c) { contas[indiceC] = c;

indiceC = indiceC + 1; }

public void cadastrarPoupanca(PoupancaD p) { poupancas[indiceP] = p;

indiceP = indiceP + 1; }

(6)

private Conta procurarConta(String numero) {

int i = 0;

boolean achou = false;

Conta resposta = null;

while ((! achou) && (i < indiceC)) {

if (contas[i].getNumero().equals(numero)) achou = true;

else

i = i + 1; }

if (achou) resposta = contas[i];

return resposta;

}

public void debitarConta(String numero, double valor) {

Conta c;

c = this.procurarConta(numero); if (c != null) c.debitar(valor); else System.out.println( "Conta inexistente!” ); }

(7)

Problemas

• Duplicação desnecessária de código:

– a definição dePoupançaDé uma simples extensão da definição de Conta

– clientes de Conta que precisam trabalhar também comPoupançaDterão que ter código especial para manipular poupanças

• Falta refletir relação entre tipos do “mundo real”

Subtipos e Subclasses

(8)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 15

Herança

• Necessidade de extender classes

– alterar classes já existentes e adicionar propriedades ou comportamentos para representar outra classe de objetos

– criar uma hierarquia de classes que “herdam” propriedades e comportamentos de outra classe e definem novas propriedades e

comportamentos

Subclasses

• Comportamento

objetos da subclasse comportam-se como

os objetos da superclasse

• Substituição

objetos da subclasse podem ser usados no

(9)

Herança

• Reuso de Código

a descrição da superclasse pode ser

usada para definir a subclasse

• Extensibilidade

algumas operações da superclasse

podem ser redefinidas na subclasse

Classe de Poupanças: Assinatura

public class Poupanca extends Conta {

public Poupanca (String numero) {}

public void renderJuros(double taxa) {}

(10)

Classe de Poupanças: Descrição

public class Poupanca extends Conta {

public Poupanca (String numero) {

super (numero);

}

public void renderJuros(double taxa) {

this.creditar(this.getSaldo()*taxa); }

}

Extends

• subclasseextendssuperclasse

• Mecanismo para definição de herança e subtipos

• Herança simples: só se pode herdar uma classe por vez

(11)

Extends: Restrições

• Atributos e métodos privados são herdados, mas não podem ser acessados diretamente

• Qualificadorprotected: visibilidade restrita

ao pacote e as subclasses de outros pacotes • Construtores não são herdados

• Construtor default só é disponível se também for disponível na superclasse

Usando Poupanças

...

Poupanca poupanca;

poupanca = new Poupanca(“21.342-7”); poupanca.creditar(500.87);

poupanca.debitar(45.00);

System.out.println(poupanca.getSaldo()); ...

(12)

Subtipos: Substituição

...

Conta conta;

conta = new Poupanca(“21.342-7”); conta.creditar(500.87);

conta.debitar(45.00);

System.out.println(conta.getSaldo()); ...

Subtipos: Verificação Dinâmica com

Casts

...

Conta conta;

conta = new Poupanca("21.342-7"); ...

conta.renderJuros(0.01); conta.imprimirSaldo(); ...

(13)

Substituição e Casts

• Nos contextos onde contas são usadas,

podem-se usar poupanças

• Nos contextos onde poupanças são usadas,

podem-se usar contas com o uso explícito de

casts

• Casts correspondem à verificação dinâmica de

tipos e podem gerar exceções (Cuidado!)

• Casts não fazem conversão de tipos

Classe Banco: Assinatura

public class Banco {

public Banco () {}

public void cadastrar(Conta conta) {}

public void creditar(String numero,

double valor) {}

public void debitar(String numero,

double valor) {}

public double getSaldo(String numero) {}

public void transferir(String contaOrigem, String contaDestino,

double valor) {} }

(14)

Subtipos: Substituição

...

Banco banco = new Banco();

banco.cadastrar(new Conta("123-4")); banco.cadastrar(new Poupanca(”567-8")); banco.creditar(”123-4",129.34);

banco.transferir(”123-4",”567-8",9.34); System.out.print(banco.getSaldo(”567-8")); ...

Exercício

• Modifique a classe Banco para que seja

possível render juros de uma poupança. Isto é, adicione um novo método que rende os juros da poupança cujo número é parâmetro deste método; a taxa de juros corrente deve ser um atributo de Banco.

(15)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 29

Interface & Código

• Herança de interface significa que a classe que herda recebe todos os métodos declarados pela superclasse que não sejam privados.

• Herança de código significa que as

implementações desses métodos também são

herdadas. Além disso, os campos que não sejam privados também são herdados.

Visibilidade & Herança

Pelo que foi dito, membros públicos são

herdados, enquanto membros privados não são. Às vezes precisamos algo intermediário: um

membro que não seja visto fora da classe mas que possa ser herdado. As linguagens OO tipicamente dão suporte a esse tipo de acesso.

(16)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 31

Mais Visibilidade em Java

• Java permite declararmos um membro que, embora não seja acessível por outras classes, é herdado por suas sub-classes.

• Para isso usamos o modificador de controle de acesso protected.

Resumo de Visibilidade em Java

• Resumindo todos os tipos de visibilidade:

– private: membros que são vistos só pelo própria classe e não são herdados por nenhuma outra; – package: membros que são vistos e herdados

pelas classes do pacote;

– protected: membros que são vistos pelas classes do pacote e herdados por qualquer outra classe; – public: membros são vistos e herdados por

(17)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 33

Herança de Membros

A int i; B int i; Pacote P1

Herança de Membros

A public int j; int i; B public int j; int i; Pacote P1

(18)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 35

Herança de Membros

A public int j; protected int k; int i; B public int j; protected int k; int i; Pacote P1

Herança de Membros

A public int j; protected int k; private int l; int i; B public int j; protected int k; int i; Pacote P1

(19)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 37

Herança de Membros

Pacote P2 P1.A C public int j; protected int k; A public int j; protected int k; private int l; int i; B public int j; protected int k; int i; Pacote P1

Herança em Java

• Quando uma classe A herda de B, diz-se que A é a sub-classe e estende B, a superclasse.

• Uma classe Java estende apenas uma outra

classea essa restrição damos o nome de

herança simples.

• Para criar uma sub-classe, usamos a palavra reservada extends.

(20)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 39

Exemplo de Herança

• Podemos criar uma classe que represente

um pixel a partir da classe Point. Afinal,

um pixel é um ponto colorido.

public class Pixel extends Point { int color;

public Pixel(int x, int y, int c) { super(x, y);

color = c; }

}

Herança de Código

• A classe Pixel herda a interface e o código da classe Point. Ou seja, Pixel passa a ter tanto os campos quanto os métodos (com suas

implementações) de Point.

Pixel px = new Pixel(1,2,0); // Pixel de cor 0 px.move(1,0); // Agora px está em (2,2)

(21)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 41

super

• Note que a primeira coisa que o construtor de Pixel faz é chamar o construtor de Point, usando, para isso, a palavra reservada super.

• Isso é necessário pois Pixel é uma extensão de Point, ou seja, ela deve inicializar sua parte Point antes de inicializar sua parte estendida. • Se nós não chamássemos o construtor da

superclasse explicitamente, a linguagem Java faria uma chamada ao construtor padrão da superclasse automaticamente.

Árvore

×

Floresta

• As linguagens OO podem adotar um modelo de hierarquia em árvore ou em floresta.

• Árvore significa que uma única hierarquia compreende todas as classes existentes, isto é, existe uma superclasse comum a todas as classes.

• Floresta significa que pode haver diversas árvores de hierarquia que não se relacionam, isto é, não existe uma superclasse comum a todas as classes.

(22)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 43

Modelo de Java

• Java adota o modelo de árvore.

• A classe Object é a raiz da hierarquia de classes à qual todas as classes existentes pertencem.

• Quando não declaramos que uma classe estende outra, ela, implicitamente, estende Object.

Superclasse Comum

• Uma das vantagens de termos uma superclasse comum, é termos uma funcionalidade comum a todos os objetos.

• Por exemplo, a classe Object define um método chamado toString que retorna um texto

descritivo do objeto.

• Um outro exemplo é o método finalize usado na destruição de um objeto, como já dito.

(23)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 45

Especialização

×

Extensão

• Uma classe pode herdar de outra para

especializá-la redefinindo métodos, sem

ampliar sua interface.

• Uma classe pode herdar de outra para

estendê-la decestendê-larando novos métodos e, dessa forma,

ampliando sua interface.

• Ou as duas coisas podem acontecer simultaneamente...

Polimorfismo

• Polimorfismo é a capacidade de um objeto tomar diversas formas.

• O capacidade polimórfica decorre diretamente do mecanismo de herança.

• Ao estendermos ou especializarmos uma classe, não perdemos compatibilidade com a superclasse.

(24)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 47

Polimorfismo de Pixel

• A sub-classe de Point, Pixel, é compatível com ela, ou seja, um pixel, além de outras coisas, é um ponto.

• Isso implica que, sempre que precisarmos de um ponto, podemos usar um pixel em seu lugar.

Exemplo de Polimorfismo

• Podemos querer criar um array de pontos. O array de pontos poderá conter pixels:

Point[] pontos = new Point[5]; // um array de pontos pontos[0] = new Point();

(25)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 49

Mais sobre Polimorfismo

• Note que um pixel pode ser usado sempre que se necessita um ponto. Porém, o contrário não é verdade: não podemos usar um ponto quando precisamos de um pixel.

Point pt = new Pixel(0,0,1); // OK! pixel é ponto. Pixel px = new Point(0,0); // ERRO! ponto não é pixel.

Conclusão

Polimorfismo é o nome formal para o fato de que quando precisamos de um objeto de determinado tipo, podemos usar uma versão mais

especializada dele. Esse fato pode ser bem

entendido analisando-se a árvore de hierarquia de classes.

(26)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 51 Objetos Materiais Animais Mamíferos Humanos Floricultores Dentistas João José Vegetais Rosas Rosas da Maria

Ampliando o Exemplo

• Vamos aumentar a classe Point para fornecer um método que imprima na tela uma

representação textual do ponto.

public class Point { ...

public void print() {

System.out.println(“Point (”+p.x+“,”+p.y+“)”); }

(27)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 53

Ampliando o Exemplo (cont.)

• Com essa modificação, tanto a classe Point quanto a classe Pixel agora possuem um método que imprime o ponto representado. • Podemos voltar ao exemplo do array de pontos

e imprimir as posições preenchidas.

Point pt = new Point(); // ponto em (0,0) Pixel px = new Pixel(0,0,0); // pixel em (0,0)

pt.print(); // Imprime: “Point (0,0)”

px.print(); // Imprime: “Point (0,0)”

• Porém, a implementação desse método não é boa para um pixel pois não imprime a cor.

• Vamos, então, redefinir o método em Pixel.

public class Pixel extends Point { ...

public void print() {

System.out.println(“Pixel (”+p.x+“,”+p.y+“,”+ p.color+“)”);

} }

(28)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 55

Ampliando o Exemplo (cont.)

• Com essa nova modificação, a classe

Pixel agora possui um método que

imprime o pixel de forma correta.

Point pt = new Point(); // ponto em (0,0) Pixel px = new Pixel(0,0,0); // pixel em (0,0)

pt.print(); // Imprime: “Point (0,0)”

px.print(); // Imprime: “Pixel (0,0,0)”

Late Binding

Voltando ao exemplo do array de pontos, agora que cada classe possui sua própria codificação para o método print, o ideal é que, ao corrermos o array imprimindo os pontos, as versões corretas dos métodos fossem usadas. Isso realmente

acontece, pois as linguagens OO usam um recurso chamado late binding.

(29)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 57

Late Binding na prática

• Graças a esse recurso, agora temos:

Point[] pontos = new Point[5]; pontos[0] = new Point();

pontos[1] = new Pixel(1,2,0);

pontos[0].print(); // Imprime: “Point (0,0)”

pontos[1].print(); // Imprime: “Pixel (1,2,0)”

Definição de Late Binding

Late Binding, como o nome sugere, é a capacidade de adiar a resolução de um método até o momento no qual ele deve ser efetivamente chamado. Ou seja, a resolução do método acontecerá em tempo de execução, ao invés de em tempo de compilação. No momento da chamada, o método utilizado será o definido pela classe real do objeto.

(30)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 59

Late Binding

×

Eficiência

O uso de late binding pode trazer perdas no desempenho dos programas visto que a cada chamada de método um processamento adicional deve ser feito. Esse fato levou várias linguagens OO a permitir a construção de métodos

constantes, ou seja, métodos cujas

implementações não podem ser redefinidas nas sub-classes.

Valores Constantes

• Java permite declarar um campo ou uma

variável local que, uma vez inicializada, tenha seu valor fixo. Para isso utilizamos o

modificador final.

class A {

final int ERR_COD1 = -1;

final int ERR_COD2 = -2; ...

(31)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 61

Métodos Constantes em Java

• Para criarmos um método constante em Java devemos, também, usar o modificador final.

public class A {

public final int f() { ...

} }

Classes Constantes em Java

• Uma classe inteira pode ser definida final. Nesse caso, em particular, a classe não pode ser estendida.

public final class A { ...

(32)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 63

Conversão de Tipo

Como dito anteriormente, podemos usar uma versão mais especializada quando precisamos de um objeto de certo tipo mas o contrário não é verdade. Por isso, se precisarmos fazer a

conversão de volta ao tipo mais especializado, teremos que fazê-lo explicitamente.

Type Casting

• A conversão explícita de um objeto de um tipo para outro é chamada type casting.

Point pt = new Pixel(0,0,1); // OK! pixel é ponto. Pixel px = (Pixel)pt; // OK! pt agora contém um pixel. pt = new Point();

px = (Pixel)pt; // ERRO! pt agora contém um ponto. pt = new Pixel(0,0,0);

(33)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 65

Mais Type Casting

Note que, assim como o late binding, o type casting só pode ser resolvido em tempo de

execução: só quando o programa estiver rodando é que poderemos saber o valor que uma dada variável terá e, assim, poderemos decidir se a conversão é válida ou não.

Subtipos: Verificação Dinâmica com

instanceof

...

Conta c = this.procurar(”567-8");

if (c instanceof Poupanca)

((Poupanca) c).renderJuros(0.01);

else

System.out.print("Poupança inexistente!"); ...

(34)

Verificação Dinâmica de Tipos

• Casts e instanceof:

– ((Tipo) variável)

– variávelinstanceofTipo

– O tipo de variável deve ser supertipo de Tipo

– O Cast “((Tipo) variável)” gera uma exceção se “variável instanceof Tipo” retornar false – Casts são essenciais para verificação estática de

tipos (compilação) Número Saldo 21.342-7 875,32 Crédito Débito

Objeto Conta Especial

R. Bônus

Bônus

(35)

Número Saldo 21.342-7 875,32 Crédito Débito

Estados de uma Conta Especial

Número Bônus Saldo 21.342-7 11,80 895,32 Crédito Débito Número Bônus Saldo 21.342-7 11,60 875,32 Crédito Débito Crédito(20) R. Bônus R. Bônus Número Saldo 21.342-7 875,32 Crédito Débito

Estados de uma Conta Especial

Número Bônus Saldo 21.342-7 0,00 887,12 Crédito Débito Número Bônus Saldo 21.342-7 11,80 875,32 Crédito Débito R. Bônus() R. Bônus R. Bônus

(36)

Contas Especiais: Assinatura

public class ContaEspecial extends Conta { public ContaEspecial(String numero) {} public void renderBonus() {}

public double getBonus() {}

public void creditar(double valor) {} }

Contas Especiais: Descrição

public class ContaEspecial extends Conta { private double bonus;

public ContaEspecial(String numero) { super (numero);

bonus = 0.0; }

(37)

public void creditar(double valor) { bonus = bonus + (valor * 0.01); super.creditar(valor);

}

public void renderBonus() { super.creditar(bonus); bonus = 0;

}

public double getBonus() { return bonus;

}

Redefinição de Métodos

• Preservação da assinatura: tipos dos

argumentos e resultados da redefinição têm

que ser iguaisaos tipos da definição

• Semântica e Visibilidade dos métodos redefinidos deve ser preservada

• Só é possível acessar a definição dos métodos

(38)

Usando Contas Especiais

...

ContaEspecial contae;

contae = new ContaEspecial("21.342-7"); contae.creditar(200.00); contae.debitar(100.00); contae.renderBonus(); System.out.print(contae.getSaldo()); ...

Ligações Dinâmicas

... Conta conta;

conta = new ContaEspecial("21.342-7"); ((Conta)conta).creditar(200.00);

conta.debitar(100.00);

((ContaEspecial) conta).renderBonus(); System.out.print(conta.getSaldo()); ...

(39)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 77

Ligações Dinâmicas

Conta conta;

conta = new ContaEspecial("21.342-7"); ((Conta)conta).creditar(200.00);

“Como existe uma redefinição do método creditar na classe ContaEspecial,o Cast serve para informar a Java qual definição estamos interessados.”

Ligações Dinâmicas

Conta conta;

conta = new ContaEspecial("21.342-7"); conta.debitar(100.00);

“Já o método debitar só existe na classe Conta, então Java acessa sua definição diretamente.”

(40)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 79

Ligações Dinâmicas

Conta conta;

conta = new ContaEspecial("21.342-7"); ((ContaEspecial) conta).renderBonus();

“Finalmente, o método renderBonus só existe na classe ContaEspecial. Nesse caso, Java deve ser informado através de um Cast onde localizar sua definição. Se isso não for feito, uma exceção será gerada.”

Ligações Dinâmicas

• Dois métodos com o mesmo nome e tipo:

– definição e redefinição, qual usar?

• O código é escolhido dinamicamente (em

tempo de execução) e não estaticamente (em

tempo de compilação)

• Escolha se dá baseado na classe do objeto associado à variável destino do método

(41)

Exercício

• Modifique a classe Banco para que seja possível computar o bônus de uma conta especial. Foi necessário redefinir algum método de Banco? Justifique a sua resposta.

Classe Banco: Assinatura

public class Banco {

public Banco () {}

public void cadastrar(Conta conta) {}

public void creditar(String numero,

double valor) {}

public void debitar(String numero,

double valor) {}

public double getSaldo(String numero) {}

public void transferir(String contaOrigem, String contaDestino,

double valor) {} }

(42)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 83

Classes Abstratas

• Ao criarmos uma classe para ser estendida, às vezes codificamos vários métodos usando um método para o qual não sabemos dar uma

implementação, ou seja, um método que só sub-classes saberão implementar.

• Uma classe desse tipo não deve poder ser instanciada pois sua funcionalidade está incompleta. Tal classe é dita abstrata.

Classes Abstratas em Java

• Java suporta o conceito de classes abstratas: podemos declarar uma classe abstrata usando o modificador abstract.

• Além disso, métodos podem ser declarados abstratos para que suas implementações fiquem adiadas para as sub-classes. Para tal, usamos o mesmo modificador abstract e omitimos a implementação.

(43)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 85

Exemplo de Classe Abstrata

public abstract class Drawing {

public abstract void draw(); public abstract BBox getBBox(); public boolean contains(Point p) {

BBox b = getBBox();

return (p.x>=b.x && p.x<b.x+b.width && p.y>=b.y && p.y<b.y+b.height); } ... } numero saldo 21.342-7 875,32

Objeto Conta Imposto

creditar

(44)

Número getSaldo 21.342-7 875,32 Crédito Débito

Estados do Objeto Conta Imposto

numero saldo 21.342-7 875,00 debitar(20) creditar debitar Número getSaldo 21.342-7 875,32 Crédito Débito numero saldo 21.342-7 854,98 creditar debitar

Conta Imposto: Assinatura

public class ContaImposto {

public ContaImposto (String numero) {} public void creditar(double valor) {} public void debitar(double valor) {} public String getNumero() {}

public double getSaldo() {} }

(45)

Conta Imposto: Assinatura

public class ContaImpostoM extends Conta { public ContaImpostoM(String numero) {} public void debitar(double valor) {} }

Conta Imposto: Descrição

public class ContaImpostoM extends Conta { private static final double taxa = 0.0038; public ContaImpostoM (String numero) {

super (numero); }

public void debitar(double valor) { double imposto = (valor * taxa); super.debitar(valor + imposto); }

(46)

Subtipos e Subclasses

ContaImposto

Conta

Subclasses e Comportamento

• Objetos da subclasse comportam-se como os

objetos da superclasse

• Redefinições de métodos devem preservar o comportamento (semântica) do método original

• Grande impacto sobre manutenção/evolução de software...

(47)

Revisão/Otimização de Código

... double m(Conta c) { c.creditar(x); c.debitar(x); return c.getSaldo(); } ...

Modificação é correta? Em que contextos?

... double m(Conta c) { return c.getSaldo(); } ...

Subclasses e Evolução

de Software

• Deveria ser possível raciocinar sobre o código

usando-se apenasa definição dos tipos das

variáveis envolvidas (Conta)

• O comportamento do código deveria ser

independente do tipo do objeto (Conta,

ContaEspecial, ContaImposto) associado a uma dada variável em tempo de execução

(48)

Reuso sem Subtipos

Conta

Poupança ContaImpostoM

ContaEspecial

Reuso preservando Subtipos

ContaAbstrata

ContaImposto Conta

(49)

Definindo Classes Abstratas

public abstract class ContaAbstrata { private String numero;

private double saldo;

public ContaAbstrata (String numero) { this.numero = numero;

saldo = 0.0; }

public void creditar(double valor) { saldo = saldo + valor;

}

Definindo Classes Abstratas

public double getSaldo() { return saldo;

}

public String getNumeto() { return numero;

}

public abstract void debitar(double valor);

protected void setSaldo(double saldo) { this.saldo = saldo;

(50)

Classes Abstratas

• Possibilita herança de código preservando comportamento (semântica)

• Métodos abstratos:

– geralmente existe pelo menos um – são implementados nas subclasses

• Não se criam objetos:

– mas podem (devem) ter construtores, para reuso – métodos qualificados como protected para

serem acessados nas subclasses

Contas: Descrição Modificada

public class Conta extends ContaAbstrata { public Conta(String numero) {

super (numero); }

public void debitar(double valor) { this.setSaldo(getSaldo() - valor); }

(51)

Poupanças: Descrição Original

public class Poupanca extends Conta { public Poupanca(String numero) {

super (numero); }

public void renderJuros(double taxa) { this.creditar(getSaldo() * taxa); }

}

Conta Especial: Descrição Original

public class ContaEspecial extends Conta { public static final double TAXA = 0.01; private double bonus;

public ContaEspecial (String numero) { super (numero);

}

public void creditar(double valor) { bonus = bonus + (valor * TAXA); super.creditar(valor);

} ...

(52)

Conta Imposto: Descrição

public class ContaImposto extends ContaAbstrata {

public static final double TAXA = 0.0038; public ContaImposto (String numero) {

super (numero); }

public void debitar(double valor) { double imposto = valor * TAXA; double total = valor + imposto; this.setSaldo(getSaldo() – total); }

}

Substituição e Ligações Dinâmicas

...

ContaAbstrata ca, ca’;

ca = new ContaEspecial(¨21.342-7¨); ca’ = new ContaImposto(¨21.987-8¨); ca.debitar(500);

ca’.debitar(500);

System.out.println(ca.getSaldo()); System.out.println(ca’.getSaldo()); ...

(53)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 105

Classes Abstratas: Utilização

• Herdar código sem quebrar noção de subtipos, preservando o comportamento do supertipo • Generalizar código, através da abstração de

detalhes não relevantes

• Projetar sistemas, definindo as suas arquiteturas e servindo de base para a implementação progressiva dos mesmos

Contas: Projeto OO

public abstract class ContaProjeto { private String numero;

private double saldo;

public abstract void creditar(double valor); public abstract void debitar(double valor); public String getNumero() {

return numero;

protected setSaldo(double saldo) { this.saldo = saldo;

} ... }

(54)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 107

Cliente: Projeto OO

public abstract class Cliente { private String nome;

private RepositorioContatos contatos; ...

public void incluirContato(Contato contato) { contatos.incluir(contato);

}

public abstract Endereco getEndereco();

public abstract Contato getContato(String tipo); ...

}

Contato: Reuso e Subtipos

Contato

Telefone Endereco

(55)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 109

Contato: Projeto OO

public abstract class Contato { private String tipo;

public Contato (String tipo) { this.tipo = tipo;

} ...

public abstract String getInfoRotulo(); }

public abstract class Endereco extends Contato { public Endereco (String tipo) {

super (tipo); }

}

(56)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 111

Endereço Eletrônico: Projeto OO

public class EnderecoEletronico extends Endereco { private String email;

public EnderecoEletronico(String email) { super (“EnderecoEletronico”);

this.email = email; }

public String getInfoRotulo() { return (“Email: ” + email); }

}

Endereço Residencial: Projeto

public class EnderecoPostal extends Endereco { private String rua;

private String cidade; ...

public EnderecoPostal(String cidade, String rua, ...) { super (“EnderecoPostal”); this.cidade = cidade; this.rua = rua; ... }

public String getInfoRotulo() { return (“Rua: ” + rua + ...);

(57)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 113

Telefone: Projeto

public class Telefone extends Contato { private String ddd;

private String numero;

public Telefone(String ddd, String numero) { super (“Telefone”);

this.numero = numero; this.ddd = ddd;

}

public String getInfoRotulo() { return (“DDD: ” + ddd +

“Numero: “ + numero); }

}

Pessoa: Reuso e Subtipos

Pessoa

PessoaFisica PessoaJuridica

(58)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 115

Pessoa: Projeto OO

public abstract class Pessoa { private String nome;

...

public abstract String getCodigo(); }

public class PessoaFisica

extends Pessoa { private String cpf;

...

public String getCodigo() { return cpf;

} }

(59)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 117

public class PessoaJuridica

extends Pessoa { private String cnpj;

...

public String getCodigo() { return cnpj;

} }

Pessoa Jurídica: Projeto OO

public class RepositorioPessoasArray { private Pessoa[] pessoas;

...

public Pessoa procurar(String codigo) { Pessoa p = null;

boolean achou = false;

for (int i=0; i<indice && !achou; i++) { p = pessoas[i]; if (p.getCodigo().equals(codigo)) achou = true; else p = null; } return p; }

(60)

Exercícios

• Modifique a classe Banco para que seja possível armazenar todos os tipos de contas vistos em aula.

Classes Abstratas

Resumo

• Importância de redefinir métodos preservando a semântica dos métodos originais

• Cláusula abstract para classes • Cláusula abstract para métodos

(61)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 121

Interfaces

Interfaces

Herança: Simples

×

Múltipla

• O tipo de herança que usamos até agora é chamado de herança simples pois cada classe herda de apenas uma outra.

• Existe também a chamada herança múltipla onde uma classe pode herdar de várias classes.

(62)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 123

Herança Múltipla

• Herança múltipla não é suportada por todas as linguagens OO.

• Esse tipo de herança apresenta um problema quando construímos hierarquias de classes onde uma classe herda duas ou mais vezes de uma mesma superclasse. O que, na prática, torna-se um caso comum.

Problemas de Herança Múltipla

• O problema de herdar duas vezes de uma mesma classe vem do fato de existir uma

herança de código. A

(63)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 125

Compatibilidade de Tipos

Inúmeras vezes, quando projetamos uma

hierarquia de classes usando herança múltipla, estamos, na verdade, querendo declarar que a classe é compatível com as classes herdadas. Em muitos casos, a herança de código não é

utilizada.

Interfaces

• Algumas linguagens OO incorporam o conceito de duas classes serem compatíveis através do uso de compatibilidade estrutural ou da implementação explícita do conceito de

(64)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 127

Em Java

• Java não permite herança múltipla com herança de código.

• Java implementa o conceito de interface. • É possível herdar múltiplas interfaces.

• Em Java, uma classe estende uma outra classe e implementa zero ou mais interfaces.

• Para implementar uma interface em uma classe, usamos a palavra implements.

Exemplo de Interface

• Ao implementarmos o TAD Pilha, poderíamos ter criado uma interface que definisse o TAD e uma ou mais classes que a implementassem.

interface Stack { boolean isEmpty(); void push(int n); int pop(); int top(); }

(65)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 129

Membros de Interfaces

• Uma vez que uma interface não possui implementação, devemos notar que:

– seus campos devem ser públicos, estáticos e constantes;

– seus métodos devem ser públicos e abstratos.

• Como esses qualificadores são fixos, não precisamos declará-los (note o exemplo anterior).

Membros de Interfaces (cont.)

• Usando os modificadores explicitamente,

poderíamos ter declarado nossa interface

da seguinte forma:

interface Stack {

public abstract boolean isEmpty(); public abstract void push(int n); public abstract int pop();

public abstract int top(); }

(66)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 131

Pilha revisitada

class StackImpl implements Stack { private int[] data;

private int top_index; Stack(int size) {

data = new int[size]; top_index = -1;

}

public boolean isEmpty() { return (top_index < 0); } public void push(int n) { data[++top_index] = n; } public int pop() { return data[top_index--]; } public int top() { return data[top_index]; } }

Auditor de Banco

public class AuditorB {

private final static double MINIMO = 500.00; private String nome;

/* ... */

public boolean auditarBanco(Banco banco) { double saldoTotal, saldoMedio;

int numeroContas;

saldoTotal = banco.saldoTotal()

numeroContas = banco.numeroContas(); saldoMedio = saldoTotal/numeroContas; return (saldoMedio < MINIMO);

(67)

Auditor de Banco Modular

public class AuditorBM {

private final static double MINIMO = 500.00; private String nome;

/* ... */

public boolean auditarBanco(BancoModular banco){ double saldoTotal, saldoMedio;

int numeroContas;

saldoTotal = banco.saldoTotal()

numeroContas = banco.numeroContas(); saldoMedio = saldoTotal/numeroContas; return (saldoMedio < MINIMO);

} }

Problema

• Duplicação desnecessária de código • O mesmo auditor deveria ser capaz de

investigar qualquer tipo de banco que possua

operações para calcular

– o número de contas, e

(68)

Auditor Genérico

public class Auditor {

private final static double MINIMO = 500.00; private String nome;

/* ... */

public boolean auditarBanco(QualquerBanco banco){ double saldoTotal, saldoMedio;

int numeroContas;

saldoTotal = banco.saldoTotal()

numeroContas = banco.numeroContas(); saldoMedio = saldoTotal/numeroContas; return (saldoMedio < MINIMO);

} }

Definindo Interfaces

public interface QualquerBanco { double saldoTotal();

int numContas(); }

(69)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 137

Interfaces

• Caso especial de classes abstratas...

– todos os métodos são abstratos • provêem uma interface para serviços e

comportamentos

• são qualificados como public por default – não definem atributos

• definem constantes

• por default todos os “atributos” definidos em uma interface são qualificados como public, static e final

– não definem construtores

Interfaces

• Não se pode criar objetos

• Definem tipo de forma abstrata, apenas indicando a assinatura dos métodos

• Os métodos são implementados pelos subtipos (subclasses)

• Mecanismo de projeto

– podemos projetar sistemas utilizando interfaces – projetar serviços sem se preocupar com a sua

(70)

Subtipos sem Herança de Código

public class Banco implements QualquerBanco { /* ... */

}

public class BancoModular

implements QualquerBanco { /* ... */ }

implements

• classe implements interface1, interface2, ... • subtipo implements supertipo1, supertipo2, ... • Múltiplos supertipos:

– uma classe pode implementar mais de uma interface (contraste com classes abstratas...)

(71)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 141

implements

• Classe que implementa uma interface deve

definir os métodos da interface:

– classes concretastêm que implementar os métodos

– classes abstratas podem simplesmente conter métodos abstratos correspondentes aos métodos da interface

Usando Auditores

Banco b = new Banco();

BancoModular bm = new BancoModular(); Auditor a = new Auditor();

/* ... */

boolean r = a.auditarBanco(b); boolean r’ = a.auditarBanco(bm); /* ... */

(72)

Interfaces e Reusabilidade

• Evita duplicação de código através da definição de um tipo genérico, tendo como subtipos várias classes não relacionadas

• Tipo genérico pode agrupar objetos de várias classes definidas independentemente, sem compartilhar código via herança, tendo implementações totalmente diferentes • Classes podem até ter mesma semântica...

Definição de Classes: Forma Geral

class C’ extends C

implements I1, I2, ..., In { /* ... */

}

C

(73)

Subtipos com Herança Múltipla de

Assinatura

interface I

extends I1, I2, ..., In { /*... assinaturas de novos

métodos ... */

}

O que usar? Quando?

Classes (abstratas)

• Agrupa objetos com implementações compartilhadas • Define novas classes

através de herança (simples) de código

• Só uma pode ser

supertipo de outra classe

Interfaces

• Agrupa objetos com implementações diferentes

• Define novas interfaces através de herança (múltipla) de assinaturas

• Várias podem ser

(74)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 147

Cadastro de Contas:

Parametrização

public class CadastroContas {

private RepositorioContas contas;

public CadastroContas (RepositorioContas r) { if (r != null) contas = r;

}

/* ... */ }

A estrutura para armazenamento das contas é fornecida na inicialização do cadastro,

e pode depois ser trocada!

Repositório: Definição

public interface RepositorioContas { void inserir(Conta conta);

Conta procurar(String numero); boolean existe(String numero); }

(75)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 149

Repositório: Implementações

public class ConjuntoContas

implements RepositorioContas {...} public class ListaContas

implements RepositorioContas {...} public class ArrayContas

implements RepositorioContas {...} public class VectorContas

implements RepositorioContas {...}

Cadastro de Contas:

Parametrização

public void cadastrar(Conta conta) { if (conta != null) {

String numero = conta.getNumero(); if (!contas.existe(numero)) {

contas.inserir(conta); }

} }

(76)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 151

Cadastro de Contas:

Parametrização

public void debitar(String numero, double valor){ Conta conta; conta = contas.procurar(numero); if (conta != null) { conta.debitar(val); } }

Exercícios

• Que outros mecanismos de Java poderiam ter sido usados para definir o tipo

RepositorioContas?

• Explique como o mecanismo de interfaces favorece reusabilidade e extensibilidade. Justifique.

(77)

Interfaces

Resumo

• Cláusula interface • Cláusula implements

• Herança de código versus herança de assinaturas

• Interfaces e parametrização de sistemas

Parametrização de Tipos

(78)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 155

Limites de Herança

O mecanismo de herança que analisamos não resolve alguns problemas. Considere o TAD Pilha que implementamos: Ele define uma pilha de números inteiros mas isso não devia ser (e não é) necessário. Por exemplo, poderia ser útil ter uma pilha de inteiros e uma outra de Point. Podemos criar pilhas específicas mas não podemos criar todas as possíveis...

Herança

×

Parametrização

• Uma alternativa a criar novas classes para cada diferente tipo de pilha que iremos usar é

parametrizar a própria classe que implementa

a pilha.

• Várias linguagens OO suportam parametrização de tipos.

(79)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 157

Parametrização de Tipos

• Parametrizar um tipo significa passar o tipo a ser usada em alguma operação como um

parâmetro.

• No caso da pilha, poderíamos passar o tipo dos elementos que pilha deveria conter como um parâmetro do construtor, por exemplo.

Tipos de Parametrização

• Existem dois tipos de parametrização:

– Irrestrita quando o tipo a ser usado é recebido e nada é assumido sobre esse tipo;

– Restrita quando assume-se que o tipo recebido atende a propriedade qualquer como, por

exemplo, possuir uma função de comparação entre seus valores.

(80)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 159

Parametrização em Java

• Java não provê suporte direto à construção de classes parametrizadas.

• Como Java adota o modelo de hierarquia em árvore, com uma superclasse comum a todas as classes, e, além disso, mantém as informações de tipo em tempo de execução, podemos simular um TAD paramétrico usando conversão de tipos.

Verificação de Tipos

• Para simularmos parametrização em Java podemos vir a precisar alguma forma de verificação de tipos em tempo de execução. • Java mantém informações de tipo em tempo de

execução e nos permite consultá-las.

Point pt = new Point(); // pt contém um ponto boolean b = pt instanceof Pixel; // b = false pt = new Pixel(1,2,3); // pt contém um pixel b = pt instanceof Pixel; // b = true

(81)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 161

Simulando Parametrização

• Podemos mudar a definição do nosso

TAD para especificar pilhas de objetos

genéricos.

interface Stack { boolean isEmpty(); void push(Object obj); Object pop();

Object top(); }

Aninhamento de Classes

(82)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 163

Aninhamento de Classes

• Em diversas circunstâncias precisamos criar classes cujo único objetivo é auxiliar na implementação de uma outra classe. Nesses casos, podemos declarar uma classe aninhada, ou seja, declarar uma nova classe como um membro de uma outra.

• Diversas linguagens OO suportam esse recurso.

Aninhamento em Java

• Java permite dois tipos diferentes de aninhamento de tipos:

– Aninhamento estático; – Aninhamento dinâmico.

(83)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 165

Aninhamento Estático

• Gera classes e interfaces normais, cuja única singularidade é o nome, que passa a ser

qualificado pelo nome da classe que as declara. • Em particular, sendo um membro de uma classe,

uma interface ou classe aninhada está sujeita aos modificadores de controle de acesso: public, private, protected e package.

Exemplo de Aninhamento Estático

package p;

public class A {

public static class B { ...

} }

p.A a = new p.A(); p.A.B b = new p.A.B();

(84)

10/12/200 2

4 -Conceitos OO em Java Prof. Anselmo Cardoso de Paiva 167

Aninhamento Dinâmico

• Gera classes associadas a objetos.

• Cada instância da classe aninhada possui uma referência para o objeto a partir do qual ela é criada.

• Como ela está associada a um objeto, ela tem acesso a todos os membros desse objeto.

void f() { B b = new B(); b.g(); } A B class A { int i; class B { void g() {...} } void f() {...} } void g() { i = 1;

Referências

Documentos relacionados

• uma entidade adquirida possui uma patente de tecnologia. Ela tem licença de uso exclusivo fora dos Estados Unidos, em troca deste uso a entidade recebe um percentual

funcao reparativa que se consubstancia na obrigacao de devolver a vitima ao statu quo ante, seja diante da restituicao da coisa, seja atraves de um valor pecuniario que a

1701/2003 do Conselho Federal de Medicina estabeleceu critérios norteadores da publicidade médica, proibindo, por exemplo, a participa- ção de médicos em anúncios de empresas e

Based on the theory that the muscle strength of elderly in- dividuals responds differently to an activity program, ac- cording to the presence or absence of a medical diagnosis

al.,(1998) relatou que dietas ricas em ácidos graxos saturados (banha de porco) reduzem a resposta das ilhotas de Langerhans à glicose, enquanto que dietas

A maior proteólise observada para o leite UHT obtido a partir do leite cru não adicionado de CO2 não se refletiu no comportamento da viscosidade e da sedimentação do leite, que,

The choice of solvent, an ethyl-ester of ricinoleic acid or castor-oil based biodiesel, was elaborated in previous work (Zautsen et al., 2011a) and based on the

Nesse contexto, vários estudos já foram realizados para elucidar os fatores ambientais e comportamentais associados ao aumento da ocorrência de sobrepeso e de obesidade na