Você está na página 1de 49

Classes Abstratas e Interfaces Paulo Borba Centro de Informtica Universidade Federal de Pernambuco

Objeto Conta Imposto


creditar

saldo

numero

875,32 21.342-7

debitar

Estados do Objeto Conta Imposto


debitar(20)
creditar
Crdito

creditar
Crdito

saldo

getSaldo

numero

Nmero

saldo

getSaldo

numero

Nmero

875,00 21.342-7
875,32

21.342-7

854,98 21.342-7
875,32

21.342-7

debitar
Dbito

debitar
Dbito

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() {} }

Conta Imposto: Assinatura


public class ContaImpostoM extends Conta {
public ContaImpostoM(String numero) {} }

Conta Imposto: Descrio


public class ContaImpostoM extends Conta { private static final double taxa = 0.001; public ContaImpostoM (String numero) { super (numero); } public void debitar(double valor) { double imposto = (valor * taxa); super.debitar(valor + imposto); } }

Subtipos e Subclasses
ContaImposto

Conta

Subclasses e Comportamento

Objetos da subclasse comportam-se como os objetos da superclasse Redefinies de mtodos devem preservar o comportamento (semntica) do mtodo original Grande impacto sobre manuteno/evoluo de software...

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

Reviso/Otimizao de Cdigo
... double m(Conta c) { return c.getSaldo(); } ...

Modificao correta? Em que contextos?

Subclasses e Evoluo de Software

Deveria ser possvel raciocinar sobre o cdigo usando-se apenas a definio dos tipos das variveis envolvidas (Conta) O comportamento do cdigo deveria ser independente do tipo do objeto (Conta, ContaEspecial, ContaImposto) associado a uma dada varivel em tempo de execuo

Reuso sem Subtipos


Conta

Poupana

ContaImpostoM

ContaEspecial

Reuso preservando Subtipos


ContaAbstrata

Conta

ContaImposto

Poupanca

ContaEspecial

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 abstract void debitar(double valor); protected void setSaldo(double saldo) { this.saldo = saldo; } public double getSaldo() { return saldo; } /* ... */ }

Classes Abstratas

Possibilita herana de cdigo preservando comportamento (semntica) Mtodos abstratos:


Geralmente existe pelo menos um So implementados nas subclasses

No cria-se objetos:
Mas podem (devem) ter construtores, para reuso Mtodos qualificados como protected para serem acessados nas subclasses

Contas: Descrio Modificada


public class Conta extends ContaAbstrata { public Conta(String numero) { super (numero); } public void debitar(double valor) { this.setSaldo(getSaldo() - valor); } }

Poupanas: Descrio Original


public class Poupanca extends Conta { public Poupanca(String numero) { super (numero); } public void renderJuros(double taxa) { this.creditar(getSaldo() * taxa); } }

public class ContaEspecial extends Conta { public static final double taxa = 0.01; private double bonus; public ContaEspecial (String numero) { super (n); } public void creditar(double valor) { bonus = bonus + (valor * taxa); super.creditar(valor); } /* ... */

Conta Especial: Descrio Original

Conta Imposto: Descrio


public class ContaImposto extends ContaAbstrata { public static final double taxa = 0.001;

public ContaImposto (String numero) { super (numero); } public void debitar(double valor) { double imposto = valor * taxa; double total = valor + imposto; this.setSaldo(getSaldo() total); } }

Substituio e Ligaes Dinmicas


... 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()); ...

Classes Abstratas: Utilizao

Herdar cdigo sem quebrar noo de subtipos, preservando o comportamento do supertipo Generalizar cdigo, atravs da abstrao de detalhes no relevantes Projetar sistemas, definindo as suas arquiteturas e servindo de base para a implementao 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; } /* ... */ }

Cliente: Projeto OO

public abstract class Cliente { private String nome; private ConjuntoContato contatos; /* ... */ public void incluirContato(Contato contato) { contatos.incluir(contato); } public abstract Endereco getEndereco(); public abstract Contato getContato(String tipo); /* ... */ }

Contato: Reuso e Subtipos


Contato

Endereco

Telefone

EndEletronico EndPostal

Contato: Projeto OO
public abstract class Contato { private String tipo; public Contato (String tipo) { this.tipo = tipo; } public abstract String getInfoRotulo(); }

Endereo: Projeto OO
public abstract class Endereco extends Contato { public Endereco (String tipo) { super (tipo); } }

Endereo Eletrnico: 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); } }

Endereo Residencial: ProjetoEnderecoPostal extends public class

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 /*...*/); } }

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); } }

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); } }

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

Duplicao desnecessria de cdigo O mesmo auditor deveria ser capaz de investigar qualquer tipo de banco que

possua operaes para calcular


o nmero de contas, e o saldo total de todas as contas.

Auditor Genrico

public class AuditorGenerico { 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(); }

Interfaces

Caso especial de classes abstratas...


todos os mtodos so abstratos
provem uma interface para servios e comportamentos so qualificados como public por default definem constantes por default todos os atributos definidos em uma interface so qualificados como public, static e final

no definem atributos

no definem construtores

Interfaces

No pode-se criar objetos Definem tipo de forma abstrata, apenas indicando a assinatura dos mtodos Os mtodos so implementados pelos subtipos (subclasses)

Subtipos sem Herana de Cdigo


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

public class BancoModular implements QualquerBanco { /* ... */ }

implements

classe implements interface1, interface2, ... subtipo implements supertipo1, supertipo2, ...

Mltiplos supertipos:
uma classe pode implementar mais de uma interface (contraste com classes abstratas...)

implements

Classe que implementa uma interface deve definir os mtodos da interface:


classes concretas tm que implementar os mtodos classes abstratas podem simplesmente conter mtodos abstratos correspondentes aos mtodos 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); /* ... */

Interfaces e Reusabilidade
Evita duplicao de cdigo atravs da definio de um tipo genrico, tendo como subtipos vrias classes no relacionadas Tipo genrico pode agrupar objetos de vrias classes definidas de forma independente, sem compartilhar cdigo via herana, tendo implementaes totalmente diferentes Classes podem at ter mesma semntica...

Definio de Classes: Forma Geral


class C extends C implements I1, I2, ..., In { /* ... */ }
I1 I2 C C ... In

Subtipos com Herana Mltipla de Assinatura


interface I extends I1, I2, ..., In { /*... assinaturas de novos mtodos ... */ }

O que usar? Quando?


Classes (abstratas) Agrupa objetos com implementaes compartilhadas Define novas classes atravs de herana (simples) de cdigo S uma pode ser supertipo de outra classe Interfaces Agrupa objetos com implementaes diferentes Define novas interfaces atravs de herana (mltipla) de assinaturas Vrias podem ser supertipo do mesmo tipo

Cadastro de Contas: Parametrizao


public class CadastroContas { private RepositorioContas contas; public CadastroContas (RepositorioContas r) { if (r != null) contas = r; } /* ... */ }

A estrutura para armazenamento das contas fornecida na inicializao do cadastro, e pode depois ser trocada!

Repositrio: Definio
public interface RepositorioContas { void inserir(Conta conta); Conta procurar(String numero); boolean existe(String numero); }

Repositrio: Implementaes
public class ConjuntoContas implements RepositorioContas {...}
public class ListaContas implements RepositorioContas {...} public class ArrayContas implements RepositorioContas {...} public class VectorContas implements RepositorioContas {...}

Cadastro de Contas: Parametrizao


public void cadastrar(Conta conta) { if (conta != null) { String numero = conta.getNumero(); if (!contas.existe(numero)) { contas.inserir(conta); } } }

Cadastro de Contas: Parametrizao


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

Você também pode gostar