herança. o que é herança? herdar é derivar características de gerações precedentes. no mundo...

46
Herança

Upload: stefany-back-de-santarem

Post on 07-Apr-2016

223 views

Category:

Documents


0 download

TRANSCRIPT

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