Buscar

Paradigmas de Linguagens de Programação - Herança

Prévia do material em texto

Paradigmas de Linguagens
Computacionais
Henrique Rebêlo
Centro de Informática
Universidade Federal de Pernambuco
@ Henrique Rebêlo, 2018. Some rights reserved.
Except where otherwise indicated, this work is licensed under
https://creativecommons.org/licenses/by-nc-sa/3.0/deed.pt/
Herança
De volta a nossa aplicação
bancária
Objeto conta bancária
NúmeroSaldo
21.342-7875,32
creditar
debitar
As operações que 
uma conta 
pode executarO estado
atual 
da conta
Estados do objeto conta
NúmerogetSaldo
21.342-7875,32
Crédito
Débito
NúmeroSaldo
21.342-7875,32
creditar
debitar
NúmerogetSaldo
21.342-7875,32
Crédito
Débito
NúmeroSaldo
21.342-7895,32
creditar
debitar
creditar(20)
Design de conta
ContaConta
- numero : String
- saldo : double
- numero : String
- saldo : double
+ getSaldo() : double
+ creditar(double): void
+ debitar(double): void
…
+ getSaldo() : double
+ creditar(double): void
+ debitar(double): void
…
Implementação da classe conta
public class Conta{
private String numero;
private double saldo;
public Conta(String numero) {
this.numero = numero;
this.saldo = 0.0;
}
public void creditar(double valor) {
this.saldo = this.saldo + valor;
}
public String getNumero() {
return this.numero;
} 
…
}
Novo requisito
• O banco precisa trabalhar com poupanças que
rendem juros uma vez por mês
O que fazer?
Design de poupança
PoupancaPoupanca
- numero : String
- saldo : double
- numero : String
- saldo : double
+ creditar(double): void
+ debitar(double): void
+ renderJuros(double): void
…
+ creditar(double): void
+ debitar(double): void
+ renderJuros(double): void
…
Objeto poupança
NúmeroSaldo
21.342-7875,32
creditar
debitar
As operações que 
uma poupança 
pode executar
O estado
atual 
da poupança
renderJuros
Estados do objeto poupança
NúmerogetSaldo
21.342-7875,32
Crédito
Débito
NúmeroSaldo
21.342-7875,32
creditar
debitar
NúmerogetSaldo
21.342-7875,32
Crédito
Débito
NúmeroSaldo
21.342-7895,32
creditar
debitar
creditar(20)
renderJuros renderJuros
Estados do objeto poupança II
NúmerogetSaldo
21.342-7875,32
Crédito
Débito
NúmeroSaldo
21.342-7875,32
creditar
debitar
NúmerogetSaldo
21.342-7875,32
Crédito
Débito
NúmeroSaldo
21.342-7884,07
creditar
debitar
renderJuros(0.01)
renderJuros renderJuros
Assinatura classe poupança
public class Poupanca {
private String numero;
private double saldo;
public Poupanca(String numero) {…}
public void creditar(double valor) {…}
public void deditar(double valor) {…}
public String getNumero() {…}
public double getSaldo() {…}
public void setSaldo() {…}
public void renderJuros(double taxa) {…}
}
Implementando renderJuros
public class Poupanca {
private String numero;
private double saldo;
public void creditar(double valor) {
this.saldo = this.saldo + valor;
}
public void renderJuros(double taxa) {
this.creditar(this.saldo * taxa);
}
…
}
E a aplicação bancária?
Assinatura classe banco
public class Banco {
public Banco() {…}
public void cadastrarConta(Conta c) {…}
public void creditarConta(String numero, double valor) {…}
public void cadastrarPoupanca(Poupanca p) {…}
public void creditarPoupanca(String numero, double valor) {…}
}
Dados classe banco
public class Banco {
private Conta[] contas;
private int indiceC;
private Poupanca[] poupancas;
private int indiceP;
}
Métodos classe banco
public class Banco {
public void cadastrarConta(Conta c) {
this.contas[this.indiceC] = c;
this.indiceC = this.indiceC + 1;
}
public void cadastrarPoupanca(Poupanca p) {
this.poupancas[this.indiceP] = p;
this.indiceP = this.indiceP + 1;
}
}
E se ocorrer mudanças?
(change requests)
Espalhamento de mudanças
PoupancaPoupanca
- numero : String
- saldo : double
- numero : String
- saldo : double
+ creditar(double): void
+ debitar(double): void
+ renderJuros(double): void
…
+ creditar(double): void
+ debitar(double): void
+ renderJuros(double): void
…
ContaConta
- numero : String
- saldo : double
- numero : String
- saldo : double
+ creditar(double): void
+ debitar(double): void
+ getSaldo() : double
…
+ creditar(double): void
+ debitar(double): void
+ getSaldo() : double
…
Log.entry(“message”);
Log.entry(“message”);
Logging 
Problemas
What is going on?
Error-prone
Low productivity
Time consuming
What is going on?
Cloned code: no reuse
Subtipos e subclasses
Poupança
Conta
Herança
• Necessidade de estender classes
• alterar classes já existentes e adicionar propriedades ou
comportamentos para representar outra classe de 
objetos
• criar uma hierarquia de classes que “herdam” 
propriedades 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 lugar de objetos
da superclasse
Benefícios
• Reuso de código
• a descrição da superclasse pode ser usada para definer a 
subclasse
• Extensibilidade
• algumas operações da superclasse podem ser redefinidas
na subclasse
Design da hierarquia conta
ContaConta
- numero : String
- saldo : double
- numero : String
- saldo : double
+ creditar(double valor) : void
+ debitar(double valor) : void
+ creditar(double valor) : void
+ debitar(double valor) : void
PoupancaPoupanca
+ renderJuros(double taxa): void
Classe poupanca com herança
public class Poupanca extends Conta {
public Poupanca(String numero) {
super(numero);
}
public void renderJuros(double taxa) {
double juros = this.getSaldo() * taxa;
this.creditar(juros);
}
}
Extends
• Mecanismo para definição de herança e subtipos
• Herança simples: só pode-se herdar explicitamente de uma
única classe em Java
<nome da subclasse> extends <nome da superclasse>
Extends restrição #1
• Atributos e métodos privados são herdados, mas não podem
ser acessados diretamente
public class Poupanca extends Conta {
public Poupanca(String numero) {
super(numero);
}
public void renderJuros(double taxa) {
double juros = this.saldo * taxa;
this.saldo = this.saldo + juros;
}
}
public class Conta {
protected double saldo;
…
}
Extends restrição #2
• Qualificador protected: visibilidade restrita ao pacote e as 
subclasses em outros pacotes
public class Poupanca extends Conta {
public Poupanca(String numero) {
super(numero);
}
public void renderJuros(double taxa) {
double juros = this.saldo * taxa;
this.saldo = this.saldo + juros;
}
}
Extends restrição #3
• Construtor default só é disponível se também for disponível na
superclasse
public class Poupanca extends Conta {
public Poupanca() {
super();
}
…
}
Erro! Somente funciona se Conta
também tiver um construtor default
Classe que usa/testa poupanca
public class Programa {
public static void main(String args[]) {
Poupanca p = new Poupanca("123-X");
p.creditar(10.0);
p.debitar(5.0);
System.out.println("Poupanca: "+p.getNumero());
System.out.println("saldo: "+p.getSaldo());
}
}
Aplicando substituição
public class Programa {
public static void main(String args[]) {
Conta c = new Poupanca("123-X");
c.creditar(10.0);
c.debitar(5.0);
System.out.println(“Conta: "+c.getNumero());
System.out.println("saldo: "+c.getSaldo());
}
}
Métodos duplicados
• Como imprimir o saldo para classe Conta e Poupanca?
public void imprimirSaldo(Conta c) {
System.out.println(c.getSaldo());
}public void imprimirSaldo(Poupanca p) {
System.out.println(p.getSaldo());
}
Métodos duplicados!
Polimorfismo
Reuso com polimorfismo
• Como imprimir o saldo para classe Conta e Poupanca?
public void imprimirSaldo(Conta c) {
System.out.println(c.getSaldo());
}
Dynamic dispatch seleciona qual método executar!
Trata objetos do tipo
Conta ou Poupanca!
Esse código compila?
public class Programa {
public static void main(String args[]) {
Conta c = new Poupanca("123-X", 8.0);
c.renderJuros(0.01);
}
}
Este código funciona?
Subtipos: verificação dinâmica com casts
public class Programa {
public static void main(String args[]) {
Conta c = new Poupanca("123-X", 8.0);
((Poupanca)c).renderJuros(0.01);
}
}
Runtime exception com casts
public class Programa {
public static void main(String args[]) {
Conta c = new Conta("123-X", 8.0);
((Poupanca)c).renderJuros(0.01);
}
}
Erro em tempo de execução
Compile time error com casts
public class Programa {
public static void main(String args[]) {
Conta c = new Conta("123-X", 8.0);
((String)c).renderJuros(0.01);
}
}
Código sem sentido!
Como render juros apenas das contas
poupancas?
public void renderJuros(Conta [] contas) {
for(int i=0; i < contas.length; i++){
Conta c = contas[i];
c.renderJuros(0.01);
}
}
Este código funciona?
Subtipos: verificação dinâmica com 
instanceof
public void renderJuros(Conta [] contas) {
for(int i=0; i < contas.length; i++){
Conta c = contas[i];
if(c instanceof Poupanca){
((Poupanca)c).renderJuros(0.01);
}
}
}
Method overriding
public class PoupancaEsp extends Poupanca {
public PoupancaEsp(String numero) {
super(numero);
}
public void renderJuros(double taxa) {
double juros = this.getSaldo() * taxa * 0.01;
this.creditar(juros);
}
}
Juros especial!
Classes abstratas x Interfaces 
O que usar? Quando?
•Classes (abstratas)
• agrupa objetos com 
implementações
compartilhadas
• define novas classes 
através de herança
(simples) de código
• somente 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 
supertipo do mesmo tipo
Paradigmas de Linguagens
Computacionais
Henrique Rebêlo
Centro de Informática
Universidade Federal de Pernambuco
@ Henrique Rebêlo, 2018. Some rights reserved.
Except where otherwise indicated, this work is licensed under
https://creativecommons.org/licenses/by-nc-sa/3.0/deed.pt/

Continue navegando