Herança
description
Transcript of Herança
Herança
Herança
O que é herança?
Herdar é derivar características de gerações precedentes. No mundo da Programação Orientada a Objetos, o termo é associado com uma das formas de reutilização de software. Através da herança, novas classes podem ser derivadas das classes existentes. A nova classe herda propriedades e métodos da classe base. A nova classe também pode adicionar suas próprias propriedades e métodos
Herança
Para que serve a herança?
Considere a criação de uma classe ClasseB em Java.
Que métodos estão disponíveis através de uma referência para a ClasseB (isto é, um objeto)?
Herança
Herança
Suponha agora que a classe ClasseB herda de ClasseA
Que métodos estão agora disponíveis para uma referência da ClasseB (um objeto) ?
Herança
Herança
Poderoso mecanismo para o reaproveitamento de código
O objeto objB tem agora disponíveis os métodos da ClasseA sem ser necessário reescrevê-los na ClasseB
Um objeto da ClasseB também é um objeto da ClasseA.
Facilita a manutenção do código: Os métodos não são replicados. Se for necessário alterar o código do método m3, basta alterá-lo em ClasseA.
ClasseB pode "recusar" parte da herança reimplementando os métodos herdados
Herança
O método m3 agora disponível para objB é aquele implementado em ClasseB
Herança
Várias subclasses podem herdar da mesma superclasse
Herança
Em Java, não é permitido herdar de mais de uma classe
ERRADO!!!!
Herança
A hierarquia de herança pode ter vários níveis
Herança
Que métodos estão agora disponíveis para uma instância de ClasseC?
Herança
A Herança também pode surgir a partir da refatoração de classes existentes de modo a eliminar a duplicação de código
Grande quantidade de atributos e métodos duplicados...
Herança
Refatoração
Superclasse(características comuns)
Subclasses(características específicas)
Herança
O mecanismo de herança pode ser melhor entendido através do seguinte exemplo:
Herança
A classe ContaBancaria tem quatro atributos: nome: armazena o nome do cliente cpf: armazena o número do CPF do cliente numeroConta: armazena o número da conta do cliente saldo: armazena o saldo da conta
Os métodos depositar e sacar são usados para fazer um depósito ou retirada da conta bancária.
A classe ContaBancária, sozinha, não é suficiente para realizar todas as transações bancárias. Existem geralmente dois tipos de contas: a conta corrente e a conta de investimentos
Herança
Vamos derivar portanto duas subclasses que herdam da superclasse ContaCorrente
Herança
As subclasses ContaInvestimento e ContaCorrente herdam os atributos e métodos da classe ContaBancaria
Herança
Agora é possível fazer:
Apesar do método depositar não ter sido definido para a classe ContaCorrente, ele está disponível devido ao mecanismo de herança
Composição
Composição
A classe contém referências para objetos de outras classes
Estas referências são também atributos da classe
Uma maneira alternativa de estender a funcionalidade de uma classe agregando funcionalidades de outras classes
Herança vs. ComposiçãoÉ UM vs. TEM UM
Composição
O mecanismo de herança nem sempre é apropriado
Java não tem herança múltipla
Estender funcionalidade através de herança pode não ser "natural":
Uma conta de investimento é uma conta bancária
Uma conta de investimento não é uma classe DecimalFormat!
Composição
Considere a seguinte situação:
::Project2
CA
m1(...)m2(...)
CB
m3(...)m4(...)
Composição
Considere agora que é preciso estender a funcionalidade da classe CA oferecendo em sua interface também os métodos m3( ) e m4( )
Composição
1a solução: Implementar os métodos m3( ) e m4( ) na classe CA.
Desvantagem: duplicação de métodos dificulta a manutenção do
software
::Project2
CA
m1(...)m2(...)m3(...)m4(...)
CB
m3(...)m4(...)
Composição
2a solução: Herança
Desvantagens: Conceitualmente, a
classe CA pode não SER uma classe CB
Java não suporta herança múltipla. E se fosse necessário oferecer os serviços m5() e m6() de uma classe CC?
::Project2
CA
m1(...)m2(...)
CB
m3(...)m4(...)
Composição
3a solução: Composição
Composição
Que serviços estão disponíveis para uma referência da classe CA?
Composição
No entanto, é possível fazer:
Observe a utilização dos métodos m3 e m4 através de uma referência para a classe CB
Composição
Esse processo é também conhecido por delegação: a classe CA delega à classe CB a execução dos serviços m3 e m4
Observe que o atributo b na classe A é público. Diz-se então que a delegação é pública, isto é, ela é visível para os clientes da classe
Um cliente da classe CA, para usar os métodos m3 e m4, deve estar ciente da delegação e fazer:
obj.b.m3();
Composição
É possível tornar a delegação privada:
Composição
Oferecer os serviços m3 e m4 na classe CA não significa, neste caso, duplicar código. Os métodos m3 e m4 em CA são apenas uma fachada para os métodos m3 e m4 em CB
Composição
Que serviços estão agora disponíveis para uma referência da classe CA?
Observe que, agora, o cliente da classe não conhece a delegação: para ele tudo se passa como se os métodos m3 e m4 fossem implementados em CA
Composição
Um exemplo no próprio Delphi: A classe System
Para imprimir uma String no console faz-se:
System.out.println("Alo Mundo!");
método da classe PrintStream
delegação
Composição
Um serviço oferecido por uma classe pode não ser exatamente uma fachada para a classe delegada, mas uma combinação de serviços oferecidos por esta.
Observe atentamente o código a seguir:
Composição
public class Data { private int dia; private int mes; private int ano;
public Data(int d, int m, int a) { dia = d; mes = m; ano = a; }
public Data(String strData) { dia = Integer.parseInt(strData.substring(0, 2)); mes = Integer.parseInt(strData.substring(3, 5)); ano = Integer.parseInt(strData.substring(6)); }
public String toString() { // imprime a data no formato dd/mm/aaaa DecimalFormat df = new DecimalFormat("00"); return df.format(dia) + "/" + df.format(mes) + "/" + ano; }}
monta uma String no formato dd/mm/aaaa
df.format()se o campo tem apenas um dígito preenche com
um zero à esquerda
public class Empregado { private Data admissao; private Data nascimento; private String nome;
public Empregado(Data admissao, Data nascimento, String nome) { this.admissao = admissao; this.nascimento = nascimento; this.nome = nome; }
public String toString() { return "nome: " + nome + "\nnascimento: " + nascimento.toString() + "\nadmissao: " + admissao.toString(); }
}
monta uma String contendo o nome, data de
nascimento e data de admissão do Empregado
public class Teste { public static void main(String args[]) { String aux = EasyIn.getString("Data do aniversario[dd/mm/aaaa]: "); Data data1 = new Data(aux);
aux = EasyIn.getString("Data da admissao[dd/mm/aaaa]: "); Data data2 = new Data(aux);
aux = EasyIn.getString("nome: "); Empregado emp = new Empregado(data2, data1, aux); System.out.println(emp.toString()); }}
lê uma String contendo a data de aniversário e usa o método substring para separar o dia, o mês e o
ano
o mesmo para a data de admissão
instancia um objeto Empregado
invoca o método toString da classe Empregado.
Este, por sua vez, usa o método toString da classe
Data
Data do aniversario[dd/mm/aaaa]: 09/03/1974
Data da admissao[dd/mm/aaaa]: 20/04/1994
nome: Rafael Marques
nome: Rafael Marques
nascimento: 09/03/1974
admissao: 20/04/1994
Process finished with exit code 0
Composição
Vamos repetir o mesmo exemplo, dessa vez usando uma interface gráfica com o usuário
Observe a utilização das mesmas classes de negócio (Empregado e Data)
class Data { private int dia; private int mes; private int ano;
public Data(int d, int m, int a) { dia = d; mes = m; ano = a; }
public Data(String strData) { dia = Integer.parseInt(strData.substring(0, 2)); mes = Integer.parseInt(strData.substring(3, 5)); ano = Integer.parseInt(strData.substring(6)); }
public String toString() { // imprime a data no formato dd/mm/aaaa DecimalFormat df = new DecimalFormat("00"); return df.format(dia) + "/" + df.format(mes) + "/" + ano; }}
class Empregado { private Data admissao; private Data nascimento; private String nome;
public Empregado(Data admissao, Data nascimento, String nome) { this.admissao = admissao; this.nascimento = nascimento; this.nome = nome; }
public String toString() { return "nome: " + nome + "\nnascimento: " + nascimento.toString() + "\nadmissao: " + admissao.toString(); }}
public class Form extends JFrame implements ActionListener { JTextField edtNasc, edtAdm, edtNome;
public Form() { super("Composição"); Container c = getContentPane(); c.setLayout(new FlowLayout());
c.add(new JLabel("Nome:")); edtNome = new JTextField(20); c.add(edtNome); c.add(new JLabel("Nascimento:")); edtNasc = new JTextField(10); c.add(edtNasc); c.add(new JLabel("Admissão:")); edtAdm = new JTextField(10); c.add(edtAdm); JButton btnImprime = new JButton("Imprime"); c.add(btnImprime); btnImprime.addActionListener(this);
this.setSize(400, 200); this.setVisible(true); }
public static void main(String args[]) { new Form(); }
public void actionPerformed(ActionEvent e) { Data data1 = new Data(edtNasc.getText()); Data data2 = new Data(edtAdm.getText());
Empregado emp = new Empregado(data2, data1, edtNome.getText()); JOptionPane.showMessageDialog(null, emp.toString()); }}