Post on 17-Apr-2015
1
Aula 8
Polimorfismo
2003/2004 Programação Orientada para
Objectos2
protected
Acesso mais limitado que public Acesso menos limitado que private Membros com categoria de acesso protected funcionam como private para o público em geral, e como public para as classes derivadas
2003/2004 Programação Orientada para
Objectos3
protected
class A { public: A(int const a) : a(a) {}
protected: int a;};
class B : public A { public: void mostra() const { cout << a << endl; }};
2003/2004 Programação Orientada para
Objectos4
Empregado…
class Empregado { public: Empregado(string const& nome, Sexo const sexo);
string const& nome() const; Sexo sexo() const; void mostra() const;
private: string nome_; Sexo sexo_;};
Empregado::Empregado(string const& nome, Sexo const sexo) : nome_(nome), sexo_(sexo) {}
string const& Empregado::nome() const{ return nome_;}
Sexo Empregado::sexo() const{ return sexo_;}
void Empregado::mostra() const{ cout << “Nome: “ << nome() << endl << “Sexo: “ << sexo() << endl;}
2003/2004 Programação Orientada para
Objectos5
… e Chefe.
class Chefe : public Empregado { public: Chefe(string const& nome, Sexo const sexo, int const nível);
int nível() const;
void mostra() const;
private: int nível_;};
Chefe::Chefe(string const& nome, Sexo const sexo, int const nível) : Empregado(nome, sexo), nível_(nível) {}
int Chefe::nível() const{ return nível_;}
void Chefe::mostra() const{ Empregado::mostra(); cout << “Nível: “ << nível() << endl;}
Classe base.
Classe derivada. é um
Chefe::mostra() ocultaEmpregado::mostra().
2003/2004 Programação Orientada para
Objectos6
Relação de generalização
Empregado
Atributose operaçõesomitidos.
Chefe
Relação degeneralização.
2003/2004 Programação Orientada para
Objectos7
Herança pública
Classe derivada herda membros da classe base Só é necessário definir o que é novo ou especializado
Membros herdados mantêm categoria de acesso Relação é um
Corte (slicing) Ponteiros e referências do tipo da classe base podem-se
referir a objectos de classes derivadas! Ocultação
Classe derivada declara operação com mesmo nome de uma existente na classe base.
2003/2004 Programação Orientada para
Objectos8
Outras relações entre classes
Funciona como um, mas… Herança privada
Membros herdados são privados
Tem um Variável membro Composição
Ser humano tem braços Agregação
Ser humano tem relógio de pulso
2003/2004 Programação Orientada para
Objectos9
Objectivo: tratar empregados e chefes uniformemente
list<Empregado*> pessoal;
pessoal.push_back(new Empregado(“João Maria”,masculino));pessoal.push_back(new Chefe(“Ana Maria”, feminino, 4));
…
for(list<Empregado*>::iterador i = pessoal.begin(); i != pessoal.end(); ++i) (*i)->mostra();
…
for(list<Empregado*>::iterador i = pessoal.begin(); i != pessoal.end(); ++i) delete *i;
Problema: aparece tudo como empregados!
Nome: João MariaSexo: masculino
Nome: Ana MariaSexo: feminino
2003/2004 Programação Orientada para
Objectos10
Objectos
: Empregado
nome_ = “João Maria”sexo_ = masculino
: Chefe
nome_ = “Ana Maria”sexo_ = femininonível_ = 4
pessoal: list<Empregado*>
! !: Empregado* : Empregado*
Ligação.
2003/2004 Programação Orientada para
Objectos11
Operações polimórficas
class Empregado { public: Empregado(string const& nome, Sexo const sexo);
string const& nome() const; Sexo sexo() const;
virtual void mostra() const;
private: string nome_; Sexo sexo_;};
Operação polimórfica ou virtual.
Classe polimórfica.
2003/2004 Programação Orientada para
Objectos12
Operações polimórficas
class Chefe : public Empregado { public: Chefe(string const& nome, Sexo const sexo, int const nível);
int nível() const;
virtual void mostra() const;
private: int nível_;};
Sobreposição: fornecimento de um método especializado para a classe derivada que implementa a operação da classe base.
A assinatura tem de ser exactamente igual!
Classe polimórfica.
2003/2004 Programação Orientada para
Objectos13
Polimorfismo
list<Empregado*> pessoal;
pessoal.push_back(new Empregado(“João Maria”,masculino));pessoal.push_back(new Chefe(“Ana Maria”, feminino, 4));
…
for(list<Empregado*>::iterador i = pessoal.begin(); i != pessoal.end(); ++i) (*i)->mostra();
…
for(list<Empregado*>::iterador i = pessoal.begin(); i != pessoal.end(); ++i) delete *i;
Nome: João MariaSexo: masculino
Nome: Ana MariaSexo: femininoNível: 4
Selecçção do método depende do tipo do objecto e não do tipo do ponteiro.
2003/2004 Programação Orientada para
Objectos14
Distinção entre operação e método
Operação Algo que se pode invocar para uma instância de uma
classe para atingir determinado objectivo Método
Implementação da operação para uma classe concreta Invocação de uma operação leva à execução de um
método Quando há polimorfismo, a invocação de uma
operação pode levar à execução de diferentes métodos
2003/2004 Programação Orientada para
Objectos15
Ligação estática vs. dinâmica
Ligação estática (operações não polimórficas) É o compilador que decide qual o método que é
executado quando se invoca a operação
Ligação dinâmica (operações polimórficas) Só durante a execução do programa é que se
sabe que método é executado, pois depende da classe do objecto e não do ponteiro ou referência
2003/2004 Programação Orientada para
Objectos16
Polimorfismo
Classe derivada não é obrigada a sobrepor versões especializadas dos métodos da classe base: Programador que desenhou classe base entende que
classes derivadas não devem fornecer métodos especializados como implementação dessa operação
Invocação de operações polimórficas usa ligação dinâmica É menos eficiente que invocação de operações não polimórficas
2003/2004 Programação Orientada para
Objectos17
Chefe com subordinados
class Chefe : public Empregado { public: Chefe(string const& nome, Sexo const sexo, int const nível);
int nível() const; virtual void mostra() const;
void subordina(Empregado* const subordinado);
private: int nível_; list<Empregado*> subordinados;};
void Chefe::subordina(Empregado* const subordinado){ subordinados.push_back(subordinado);}
2003/2004 Programação Orientada para
Objectos18
Chefe com subordinados
list<Empregado*> pessoal; Empregado* pe = new Empregado("João Maria", masculino); pessoal.push_back(pe);
Chefe* pc = new Chefe("Ana Maria", feminino, 4); pc->subordina(pe); pessoal.push_back(pc);
for(list<Empregado*>::iterator i = pessoal.begin(); i != pessoal.end(); ++i) (*i)->mostra(); …
for(list<Empregado*>::iterator i = pessoal.begin(); i != pessoal.end(); ++i) delete *i;
É invocado o destrutor de Empregado.
2003/2004 Programação Orientada para
Objectos19
Destrutor virtual
class Empregado { public: Empregado(string const& nome, Sexo const sexo); virtual ~Empregado() {}
string const& nome() const; Sexo sexo() const;
virtual void mostra() const;
private: string nome_; Sexo sexo_;};
Regra: se uma classe é base de uma hierarquia de classes polimórficas, tem de definir um destrutor virtual!
Recomendação: Devem-se explicitar sempre as operações polimórficas (virtual).
2003/2004 Programação Orientada para
Objectos20
Veículos
Conceitos relacionados Um Automóvel é um Veículo Um Motociclo é um Veículo Uma Honda Dominator NX 650 é um Motociclo Um Audi TT é um Automóvel
2003/2004 Programação Orientada para
Objectos21
Veículos: implementação
class Veículo { … };
class Automóvel : public Veículo { … };
class Motociclo: public Veículo { … };
class HondaNX650 : public Motociclo { … };
class AudiTT : public Automóvel { … };
2003/2004 Programação Orientada para
Objectos22
Veículos: representação
Veículo
Automóvel Motociclo
HondaNX650AudiTT
Conceitos abstractos.
Conceitos concretos.
2003/2004 Programação Orientada para
Objectos23
Editor de figuras bidimensionais
class Posição { public: Posição(double const x, double const y);
double x() const; double y() const;
private: double x_; double y_;};
class Dimensão { public: Dimensão(double const largura, double const altura);
double largura() const; double altura() const;
private: double largura_; double altura_;};
class Caixa { public: Caixa(Posição const& posição, Dimensão const& dimensão);
Posição const& posição() const; Dimensão const& dimensão() const;
private: Posição posição_; Dimensão dimensão_;};
2003/2004 Programação Orientada para
Objectos24
Figuras e formas
Figura list<Forma*> figura;
Formas Quadrado Círculo …
Conceitos concretos.
Conceito abstracto.
2003/2004 Programação Orientada para
Objectos25
Classe Forma
class Forma { public: Forma(Posição const& posição);
double área() const; double perímetro() const; Posição const& posição() const; Caixa const caixaEnvolvente() const;
void movePara(Posicão const& nova_posição);
private: Posição posição_;};
2003/2004 Programação Orientada para
Objectos26
Forma: métodos
Forma::Forma(Posição const& posição) : posição_(posição){}
double Forma::área() const{ return ???;}
double Forma::perímetro() const{ return ???;}
Posição const& Forma::posição() const{ return posição_; }
Caixa const Forma::caixaEnvolvente() const{ return ???;}
void Forma::movePara(Posição const& nova_posição){ posição_ = nova_posição; }
2003/2004 Programação Orientada para
Objectos27
Classe Forma
class Forma { public: Forma(Posição const& posição); virtual ~Forma() {}
virtual double área() const; virtual double perímetro() const; Posição const& posição() const; virtual Caixa const caixaEnvolvente() const;
virtual void movePara(Posicão const& nova_posição);
private: Posição posição_;};
Base de uma hierarquia de classes polimórficas.
2003/2004 Programação Orientada para
Objectos28
Classe Círculo
class Círculo : public Forma { public: Círculo(Posição const& posição, double const raio);
virtual double área() const; virtual double perímetro() const; virtual Caixa const caixaEnvolvente() const;
double raio() const;
private: double raio_;};
Não é polimórfico: não pode ser especializado.
2003/2004 Programação Orientada para
Objectos29
Círculo: métodos
Círculo::Circulo(Posição const& posição, double const raio) : Forma(posição), raio_(raio) {}
double Círculo::área() const{ return 2.0 * pi * raio(); }
double Círculo::perímetro() const{ return pi * raio() * raio(); }
Caixa const Círculo::caixaEnvolvente() const{ return Caixa(Posição(posição().x() - raio(), posição().y() - raio()), Dimensão(2.0 * raio(), 2.0 * raio()); }
double Círculo:: raio() const{ return raio_; }
2003/2004 Programação Orientada para
Objectos30
Classe abstracta Forma
class Forma { public: Forma(Posição const& posição); virtual ~Forma() = 0;
virtual double área() const = 0; virtual double perímetro() const = 0; Posição const& posição() const; virtual Caixa const caixaEnvolvente() const = 0;
virtual void movePara(Posicão const& nova_posição);
private: Posição posição_;};
Operações abstractas.Operações abstractas.
Classe abstracta: classe com operações abstractas.
Destrutor abstracto.
2003/2004 Programação Orientada para
Objectos31
Forma: métodos
Forma::Forma(Posição const& posição) : posição_(posição){}
Forma::~Forma(){}
Posição const& Forma::posição() const{ return posição_; }
void Forma::movePara(Posição const& nova_posição){ posição_ = nova_posição; }
Apesar de abstracto, o destrutor tem de ser implementado.
Classes abstractase operações abstractas ou puramente virtuais em itálico.
Alternativamente pode-se usar:
Forma {abstract}
-posição_: Posição
«constructor»+Forma(posição: Posição)«query»+área(): double+perímetro(): double+Posição(): Posição+caixaEnvolvente(): Caixa«update»+movePara(nova_posição: Posição)
«query» = inspector
«update» = modificador
Quadrado Círculo
-raio_: double
«constructor»+Círculo(posição: Posição, raio: double)«query»+área(): double+perímetro(): double+caixaEnvolvente(): Caixa+raio(): double
Forma
2003/2004 Programação Orientada para
Objectos33
Mais algumas notas...
Uma declaração de uma rotina membro indica a presença de uma operação da classe
Uma definição de uma rotina membro indica a presença de um método que implementa uma operação da classe
Uma operação abstracta não precisa de ser definida Uma classe que declare uma operação abstracta, diz-se também uma
classe abstracta Uma classe sem quaisquer operações abstractas é uma classe concreta Uma classe derivada que herde das classes base operações abstractas,
só é concreta se fornecer métodos que implementem cada uma dessas operações
Uma classe abstracta não pode ser instanciada
2003/2004 Programação Orientada para
Objectos34
Aula 8: Sumário
Categorias de acesso: acesso protegido Polimorfismo e operações polimórficas ou virtuais
Operações polimórficas Destrutores polimórficos Ligação estática vs. dinâmica Distinção entre operação e método
Classes e operações abstractas Operações abstractas ou puramente virtuais Classes abstractas Classes concretas