Baixe o app para aproveitar ainda mais
Prévia do material em texto
Paradigmas de Linguagens Computacionais Henrique Rebêlo Centro de Informática Universidade Federal de Pernambuco @ Henrique Rebêlo, 2016. 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(Contas [] 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, 2016. Some rights reserved. Except where otherwise indicated, this work is licensed under https://creativecommons.org/licenses/by-nc-sa/3.0/deed.pt/
Compartilhar