Aula 8 Polimorfismo 1 protected 2 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 Objectos protected class A { public: A(int const a) : a(a) {} protected: int a; }; class B : public A { public: void mostra() const { cout << a << endl; } }; 3 2003/2004 Programação Orientada para Objectos Empregado… class Empregado { public: Empregado(string const& nome, Sexo const sexo); string const& Empregado::nome() const { return nome_; } string const& nome() const; Sexo sexo() const; void mostra() const; Sexo Empregado::sexo() const { return sexo_; } private: string nome_; Sexo sexo_; }; Empregado::Empregado(string const& nome, Sexo const sexo) : nome_(nome), sexo_(sexo) {} 4 void Empregado::mostra() const { cout << “Nome: “ << nome() << endl << “Sexo: “ << sexo() << endl; } 2003/2004 Programação Orientada para Objectos … e Chefe. Classe derivada. Chefe::mostra() oculta Empregado::mostra(). é um 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_; }; 5 Classe base. 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; } 2003/2004 Programação Orientada para Objectos Relação de generalização Empregado Atributos e operações omitidos. Relação de generalização. Chefe 6 2003/2004 Programação Orientada para Objectos Herança pública Classe derivada herda membros da classe base 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 7 Só é necessário definir o que é novo ou especializado Classe derivada declara operação com mesmo nome de uma existente na classe base. 2003/2004 Programação Orientada para Objectos Outras relações entre classes Funciona como um, mas… Herança privada Tem um Variável membro Composição Ser humano tem braços Agregação 8 Membros herdados são privados Ser humano tem relógio de pulso 2003/2004 Programação Orientada para Objectos Objectivo: tratar empregados e chefes uniformemente Problema: aparece tudo como empregados! 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(); Nome: João Maria Sexo: masculino … for(list<Empregado*>::iterador i = pessoal.begin(); i != pessoal.end(); ++i) delete *i; 9 2003/2004 Nome: Ana Maria Sexo: feminino Programação Orientada para Objectos Objectos pessoal: list<Empregado*> ! 10 : Empregado* : Empregado* : Empregado : Chefe nome_ = “João Maria” sexo_ = masculino nome_ = “Ana Maria” sexo_ = feminino nível_ = 4 2003/2004 ! Ligação. Programação Orientada para Objectos Operações polimórficas Classe polimórfica. 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. }; 11 2003/2004 Programação Orientada para Objectos Operações polimórficas Classe polimórfica. class Chefe : public Empregado { public: Chefe(string const& nome, Sexo const sexo, int const nível); A assinatura tem de ser exactamente igual! int nível() const; virtual void mostra() const; private: int nível_; }; 12 2003/2004 Sobreposição: fornecimento de um método especializado para a classe derivada que implementa a operação da classe base. Programação Orientada para Objectos Selecçção do método depende do tipo do objecto e não do tipo do ponteiro. 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(); Nome: João Maria Sexo: masculino … for(list<Empregado*>::iterador i = pessoal.begin(); i != pessoal.end(); ++i) delete *i; 13 2003/2004 Nome: Ana Maria Sexo: feminino Nível: 4 Programação Orientada para Objectos Distinção entre operação e método Operação Método 14 Algo que se pode invocar para uma instância de uma classe para atingir determinado objectivo 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 Objectos Ligação estática vs. dinâmica Ligação estática (operações não polimórficas) Ligação dinâmica (operações polimórficas) 15 É o compilador que decide qual o método que é executado quando se invoca a operação 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 Objectos 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 16 É menos eficiente que invocação de operações não polimórficas 2003/2004 Programação Orientada para Objectos 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); } 17 2003/2004 Programação Orientada para Objectos 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 != (*i)->mostra(); … pessoal.end(); ++i) for(list<Empregado*>::iterator i = pessoal.begin(); i != pessoal.end(); ++i) delete *i; É invocado o destrutor de Empregado. 18 2003/2004 Programação Orientada para Objectos Destrutor virtual class Empregado { public: Empregado(string const& nome, Sexo const sexo); virtual ~Empregado() {} Regra: se uma classe é base de uma hierarquia de classes polimórficas, tem de definir um destrutor virtual! string const& nome() const; Sexo sexo() const; virtual void mostra() const; private: string nome_; Sexo sexo_; }; 19 Recomendação: Devem-se explicitar sempre as operações polimórficas (virtual). 2003/2004 Programação Orientada para Objectos Veículos 20 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 Objectos 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 { … }; 21 2003/2004 Programação Orientada para Objectos Veículos: representação Conceitos abstractos. Veículo Automóvel Motociclo Conceitos concretos. AudiTT 22 HondaNX650 2003/2004 Programação Orientada para Objectos 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; 23 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 Objectos Figuras e formas Figura Formas 24 list<Forma*> figura; Conceito abstracto. Quadrado Círculo … Conceitos concretos. 2003/2004 Programação Orientada para Objectos 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_; }; 25 2003/2004 Programação Orientada para Objectos Forma: métodos Forma::Forma(Posição const& posição) : posição_(posição) {} Caixa const Forma:: caixaEnvolvente() const { return ???; } double Forma::área() const { return ???; } void Forma:: movePara(Posição const& nova_posição) { posição_ = nova_posição; } double Forma::perímetro() const { return ???; } Posição const& Forma::posição() const { return posição_; } 26 2003/2004 Programação Orientada para Objectos Classe Forma class Forma { public: Forma(Posição const& posição); virtual ~Forma() {} virtual virtual Posição virtual Base de uma hierarquia de classes polimórficas. double área() const; double perímetro() const; const& posição() const; Caixa const caixaEnvolvente() const; virtual void movePara(Posicão const& nova_posição); private: Posição posição_; }; 27 2003/2004 Programação Orientada para Objectos 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_; }; 28 Não é polimórfico: não pode ser especializado. 2003/2004 Programação Orientada para Objectos Círculo: métodos double Círculo::área() const { return 2.0 * pi * 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::perímetro() const { return pi * raio() * raio(); } double Círculo:: raio() const { return raio_; } Círculo:: Circulo(Posição const& posição, double const raio) : Forma(posição), raio_(raio) {} 29 2003/2004 Programação Orientada para Objectos Classe abstracta Forma class Forma { public: Forma(Posição const& posição); virtual ~Forma() = 0; virtual virtual Posição virtual Classe abstracta: classe com operações abstractas. Destrutor abstracto. double área() const = 0; double perímetro() const = 0; const& posição() const; Caixa const caixaEnvolvente() const = 0; Operações abstractas. virtual void movePara(Posicão const& nova_posição); private: Posição posição_; }; 30 2003/2004 Programação Orientada para Objectos Forma: métodos Forma::Forma(Posição const& posição) : posição_(posição) {} Forma::~Forma() {} Apesar de abstracto, o destrutor tem de ser implementado. Posição const& Forma::posição() const { return posição_; } void Forma::movePara(Posição const& nova_posição) { posição_ = nova_posição; } 31 2003/2004 Programação Orientada para Objectos Forma -posição_: Posição «query» = inspector «update» = modificador «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) Quadrado Classes abstractas e operações abstractas ou puramente virtuais em itálico. Alternativamente pode-se usar: Forma {abstract} Círculo -raio_: double «constructor» +Círculo(posição: Posição, raio: double) «query» +área(): double +perímetro(): double +caixaEnvolvente(): Caixa +raio(): double Mais algumas notas... 33 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 Objectos Aula 8: Sumário Categorias de acesso: acesso protegido Polimorfismo e operações polimórficas ou virtuais Classes e operações abstractas 34 Operações polimórficas Destrutores polimórficos Ligação estática vs. dinâmica Distinção entre operação e método Operações abstractas ou puramente virtuais Classes abstractas Classes concretas 2003/2004 Programação Orientada para Objectos