Aula 7 - Herança 1 Herança pública: relação é um. A relação tem um. A relação é composto por um. Ponteiros, referências e corte (slicing). Derivação: classe base e classe derivada. Construtores e destrutores com herança. Ocultação. Hierarquias de classes: derivações de derivações. Possibilidade de herança múltipla. Problemas por resolver: necessidade de polimorfismo. Herança privada: redução/alteração de interfaces. Políticas de acesso. 2002/2003 Programação Orientada para Objectos Relação de generalização Empregado Atributos e operações omitidos Relação de generalização Chefe 2 2002/2003 Programação Orientada para Objectos Impacto da modelação da relação Corte (ou slicing) Chefe ana_maria(“Ana Maria”, feminino, 4); Empregado sósia_da_ana_maria_como_empregado = ana_maria; 3 Cópia da Ana Maria cortando tudo aquilo que a torna chefe. Não é muito útil: a evitar! 2002/2003 Programação Orientada para Objectos Impacto da modelação da relação list<Empregado*> empregados; empregados.push_back(new Empregado("João Maria", masculino)); empregados.push_back(new Chefe("Ana Maria", feminino, 4)); ... for(list<Empregado*>::const_iterator i = empregados.begin(); i != empregados.end(); ++i) { (*i)->mostra(); cout << endl; } 4 2002/2003 Programação Orientada para Objectos Solução 1: distinção interna do tipo de Empregado class Empregado { public: enum Tipo {empregado, chefe}; Empregado(Tipo const tipo, string const& nome, Sexo const sexo, int const nível = 0); string const& nome() const; Sexo sexo() const; int nível() const; void mostra() const; 5 2002/2003 private: string nome_; Sexo sexo_; int nível_; Tipo tipo; }; Uma só classe representa todos os tipos de empregados. Programação Orientada para Objectos Problemas da solução 1 Construtor teria de prever todos os casos e verificar todas as combinações impossíveis. Todos os métodos com especializações para cada tipo de empregado seriam monstruosos, dominados por inúmeros e gigantescos switch… Código: 6 difícil de compreender. difícil de estender. difícil de alterar. difícil de depurar. 2002/2003 Programação Orientada para Objectos Solução 2: um Empregado dentro de um Chefe class Chefe { public: Chefe(string const& nome, Sexo const sexo, int const nível); string const& nome() const; Sexo sexo() const; int nível() const; void mostra() const; ... inline void Chefe::mostra() const { empregado.mostra(); cout << "Nível: " << nível() << endl; } private: Empregado empregado; int nível_; }; 7 Duas classes: 2002/2003 Chefe delega em empregado. Permite poupar código. Programação Orientada para Objectos Problemas da solução 2 8 Ainda não é possível tratar um chefe como se de um empregado se tratasse. Dá a sensação que os chefes possuem fisicamente um pequenino homúnculo dentro deles encarregue de trabalhar por eles... O nosso código não corresponde ao que queremos modelar, o que é sempre má ideia. 2002/2003 Programação Orientada para Objectos Solução: herança pública 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_; }; inline int Chefe::nível() const { return nível_; } 9 2002/2003 Programação Orientada para Objectos Solução: herança pública Ocultação (e especialização do método da classe base) inline void Chefe::mostra() const { Empregado::mostra(); cout << "Nível: " << nível() << endl; } Construtor inline Chefe::Chefe(string const& nome, Sexo const sexo, int const nível) : Empregado(nome, sexo), nível_(nível) {} 10 2002/2003 Programação Orientada para Objectos Hierarquias de classes Veículo VeículoTerrestre VeículoAéreo Helicóptero VeículoNaval Avião Hidroavião 11 2002/2003 Programação Orientada para Objectos Herança privada (I) 12 Os métodos públicos da classe base tornam-se privados da classe derivada! Não é estabelecida relação é um entre a classe derivada e a classe base. Sempre que um conceito for diferente de outro, mas puder ser implementado à sua custa com pequenas variações (normalmente, restrições da interface), então pode-se usar. No fundo, uma herança privada estabelece um tipo especial de relação: funciona como um… mas… 2002/2003 Programação Orientada para Objectos Herança privada (II) class PilhaDeInt { public: typedef ListaDeInt::Item Item; class PilhaDeInt : private ListaDeInt { public: typedef ListaDeInt::Item Item; int altura() const; bool estáVazia() const; int altura() const; bool estáVazia() const; Item const& topo() const; Item const& topo() const; Item& topo(); Item& topo(); void põe(Item const& novo_item); void tiraItem(); private: ListaDeInt lista; }; 13 void põe(Item const& novo_item); void tiraItem(); }; 2002/2003 Programação Orientada para Objectos Herança privada (III) class PilhaDeInt : private ListaDeInt { public: using ListaDeInt::Item; class PilhaDeInt : private ListaDeInt { public: using ListaDeInt::Item; int altura() const; using ListaDeInt::comprimento; using ListaDeInt::estáVazia; using ListaInt::estáVazia; using ListaDeInt::trás; Item const& topo() const; using ListaDeInt::põeAtrás; using ListaDeInt::tiraDeTrás; Item& topo(); }; void põe(Item item); void tiraItem(); }; 14 2002/2003 Programação Orientada para Objectos