A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

1 Aula 7 Herança. 2003/2004 Programação Orientada para Objectos 2 Conceitos fundamentais: Herança Polimorfismo Ligação dinâmica.

Apresentações semelhantes


Apresentação em tema: "1 Aula 7 Herança. 2003/2004 Programação Orientada para Objectos 2 Conceitos fundamentais: Herança Polimorfismo Ligação dinâmica."— Transcrição da apresentação:

1 1 Aula 7 Herança

2 2003/2004 Programação Orientada para Objectos 2 Conceitos fundamentais: Herança Polimorfismo Ligação dinâmica

3 2003/2004 Programação Orientada para Objectos 3 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_; }; inline Empregado::Empregado(string const& nome, Sexo const sexo) : nome_(nome), sexo_(sexo) {}

4 2003/2004 Programação Orientada para Objectos 4 Empregado inline string const& Empregado:: nome() const { return nome_; } inline Sexo Empregado:: sexo() const { return sexo_; } inline void Empregado:: mostra() const { cout << "Nome: " << nome() << endl << "Sexo: " << sexo() << endl; }

5 2003/2004 Programação Orientada para Objectos 5 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; private: string nome_; Sexo sexo_; int nível_; }; inline Chefe::Chefe(string const& nome, Sexo const sexo, int const nível) : nome_(nome), sexo_(sexo), nível_(nível) { }

6 2003/2004 Programação Orientada para Objectos 6 Chefe inline string const& Chefe::nome() const { return nome_; } inline Sexo Chefe::sexo() const { return sexo_; } inline int Chefe::nível() const { return nível_; } inline void Chefe::mostra() const { cout << "Nome: " << nome() << endl << "Sexo: " << sexo() << endl << "Nível: " << nível() << endl; }

7 2003/2004 Programação Orientada para Objectos 7 Problemas Repetição de código Quase tudo igual entre Empregado e Chefe Não há relação explícita entre as duas classes (o que é conceptualmente falso) Empregado e Chefe são totalmente independentes, embora se saiba que um chefe é um empregado!

8 2003/2004 Programação Orientada para Objectos 8 Instanciação vs. especialização Eu sou um humano Instanciação Relação entre uma instância ou objecto e a sua classe: eu sou um objecto da classe dos humanos Um humano é um mamífero Especialização (ou generalização) Relação entre duas classes: os humanos são mamíferos

9 2003/2004 Programação Orientada para Objectos 9 Conceitos e implementações Língua naturalC++ Nome comum: humano Classe: Humano Definida como: class Humano { //... }; Nome próprio: "Zé"Variável: zé "O Zé é um humano." Definição de variável: Humano zé;

10 2003/2004 Programação Orientada para Objectos 10 Relação de generalização Empregado Atributos e operações omitidos. Chefe Relação de generalização.

11 2003/2004 Programação Orientada para Objectos 11 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; Cópia da Ana Maria cortando tudo aquilo que a torna chefe. Não é muito útil: a evitar!

12 2003/2004 Programação Orientada para Objectos 12 Impacto da modelação da relação list empregados; empregados.push_back(new Empregado("João Maria", masculino)); empregados.push_back(new Chefe("Ana Maria", feminino, 4));... for(list ::const_iterator i = empregados.begin(); i != empregados.end(); ++i) { (*i)->mostra(); cout << endl; }

13 2003/2004 Programação Orientada para Objectos 13 Representação da lista em UML : Empregado nome_ = João Maria sexo_ = masculino : Chefe nome_ = Ana Maria sexo_ = feminino nível_ = 4 pessoal : list !! : Empregado* Ligação.

14 2003/2004 Programação Orientada para Objectos 14 Impacto da modelação da relação: Resultado desejado Nome: João Maria Sexo: masculino Nome: Ana Maria Sexo: feminino Nível: 4

15 2003/2004 Programação Orientada para Objectos 15 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;

16 2003/2004 Programação Orientada para Objectos 16 Solução 1: distinção interna do tipo de Empregado private: string nome_; Sexo sexo_; int nível_; Tipo tipo; } inline void Empregado::mostra() const { cout << Nome: << nome() << endl << Sexo: << sexo() << endl; if(tipo == chefe) cout << Nível: << nível() << endl; } Uma só classe representa todos os tipos de empregados.

17 2003/2004 Programação Orientada para Objectos 17 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: difícil de compreender difícil de estender difícil de alterar difícil de depurar

18 2003/2004 Programação Orientada para Objectos 18 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; private: Empregado empregado; int nível_; };

19 2003/2004 Programação Orientada para Objectos 19 Solução 2: um Empregado dentro de um Chefe... inline void Chefe::mostra() const { empregado.mostra(); cout << "Nível: " << nível() << endl; } Duas classes: Chefe delega em empregado. Permite poupar código.

20 2003/2004 Programação Orientada para Objectos 20 Problemas da solução 2 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

21 2003/2004 Programação Orientada para Objectos 21 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_; }

22 2003/2004 Programação Orientada para Objectos 22 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) : ???? {}

23 2003/2004 Programação Orientada para Objectos 23 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) : nome_(nome), sexo_(sexo), nível_(nível) {}

24 2003/2004 Programação Orientada para Objectos 24 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) {}

25 2003/2004 Programação Orientada para Objectos 25 Construção e destruição Ordem de construção: Primeiro as classes base, por ordem de declaração no cabeçalho da classe derivada Depois os atributos, por ordem de declaração no corpo da classe Finalmente é executado o corpo do construtor Destruição ocorre pela ordem inversa!

26 2003/2004 Programação Orientada para Objectos 26 Construção e destruição class Z { //... }; class D : public A, public B { public: D(int i, Z const& z); ~D();... private: static int const dim = 10; int i; Z const z; float m[dim]; int* pi; }; D::D(int i, Z const& z) : i(i), z(z), pi(new int(10)) { for(int i = 0; i != dim; ++i) m[i] = 0; } D::~D() { delete pi; }

27 2003/2004 Programação Orientada para Objectos 27 Ordem de construção Construtor de A, para inicialização dos atributos herdados de A Construtor de B, para inicialização dos atributos herdados de B Construtor de int, para inicialização do atributo i Construtor de Z, para inicialização do atributo constante z Construtor de pi, para inicialização do atributo pi com o endereço de uma nova variável dinâmica Atributos de tipos básicos ou deles derivados não têm quaisquer construtores invocados implicitamente (é o caso do atributo m ) Corpo do construtor, onde se inicializa a matriz m

28 2003/2004 Programação Orientada para Objectos 28 Ordem de destruição Primeiro é executado o corpo do destrutor Depois são invocados os destrutores de todos os atributos de instância da classe derivada, por ordem inversa de declaração Finalmente são invocados os destrutores de todas as classes base por ordem inversa à do seu aparecimento na especificação das heranças na definição da classe derivada

29 2003/2004 Programação Orientada para Objectos 29 Conceitos e implementações Língua naturalC++ Nome comum: humano Classe: Humano Definida como: class Humano {}; Nome próprio: "Zé"Variável: zé "O Zé é um humano." Definição de variável: Humano zé; "Um humano é um mamífero", ou "Qualquer humano é um mamífero". Derivação de classe: class Humano : public Mamífero { };

30 2003/2004 Programação Orientada para Objectos 30 Herança pública: questões Qual é a base e qual é a derivada? Qual o sentido (direcção) da relação é um? Categorias de acesso O que é privado na classe base não pode ser mexido na classe derivada O que é público na classe base pode ser mexido por toda a gente, mesmo a classe derivada Classe derivada tem acesso directo ao nome? Ambas têm método mostra(). Que significa? Classe derivada herdou da classe base, acrescentou inspector para o nível e tem de especializar método mostra() Fornece versão, ocultando e especializando a versão da classe base

31 2003/2004 Programação Orientada para Objectos 31 Herança pública: questões class D : public A, public B, public C {... }; Cria nova classe D derivada das classes base A, B e C Classe derivada herda todos os membros das classes base Membros privados da classe base não ficam acessíveis directamente a partir dos métodos da classe derivada Se não fosse assim, estar-se-ia a abrir a porta da parte privada de uma classe a quem quer que definisse uma classe sua derivada, violando-se com isso o princípio do encapsulamento

32 2003/2004 Programação Orientada para Objectos 32 Herança pública A herança ou derivação fez-se usando a palavra chave public : Membros públicos da classe base são herdados como membros públicos da classe derivada (daí que não seja necessário redefinir as operações nome() e sexo() ) Quaisquer instâncias da classe derivada são compatíveis com instâncias da classe base, o mesmo se passando com ponteiros e referências

33 2003/2004 Programação Orientada para Objectos 33 Herança em C++ Possibilita Chefe o_zé("Zé Maria", masculino, 4); Empregado& de_novo_o_zé = o_zé; Empregado* ponteiro_para_o_zé = &zé; ou void pagaSalário() // capaz de lidar com qualquer tipo específico de empregado. { //... }

34 2003/2004 Programação Orientada para Objectos 34 Solução: completa? Problema ainda não resolvido: list empregados; empregados.push_back(new Empregado("João Maria", masculino)); empregados.push_back(new Chefe("Ana Maria", feminino, 4)); //... for(list const_iterator i = empregados.begin(); i != empregados.end(); ++i) { (*i)->mostra(); cout << endl; }

35 2003/2004 Programação Orientada para Objectos 35 Diagrama UML : Empregado nome_ = João Maria sexo_ = masculino : Chefe nome_ = Ana Maria sexo_ = feminino nível_ = 4 pessoal : list !! : Empregado* Ligação.

36 2003/2004 Programação Orientada para Objectos 36 Solução: incompleta Método mostra() executado aquando da invocação da operação mostra() depende do ponteiro através do qual se faz a invocação e não do tipo do objecto apontado! Nome: João Maria Sexo: masculino Nome: Ana Maria Sexo: feminino

37 2003/2004 Programação Orientada para Objectos 37 Solução: incompleta Ligação entre operação invocada e método executado é estática (decidida pelo compilador) Falta polimorfismo Permite que operações realizadas sobre objectos apontados por ponteiros de um único tipo terem comportamentos diversos consoante o objecto apontado Falta ligação dinâmica entre a operação invocada e o método executado (decidida durante a execução do programa)

38 2003/2004 Programação Orientada para Objectos 38 Hierarquias de classes Veículo VeículoAéreoVeículoTerrestreVeículoNaval HelicópteroAvião Hidroavião

39 2003/2004 Programação Orientada para Objectos 39 Herança privada (I) 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 Estabelece tipo especial de relação: funciona como um… mas… Conceito a implementar diferente de outro com pequenas variações (normalmente, restrições da interface)

40 2003/2004 Programação Orientada para Objectos 40 Herança privada (II) class PilhaDeInt { public: typedef ListaDeInt::Item Item; int altura() const; bool estáVazia() const; Item const& topo() const; Item& topo(); void põe(Item const& novo_item); void tiraItem(); private: ListaDeInt lista; }; class PilhaDeInt : private ListaDeInt { public: typedef ListaDeInt::Item Item; int altura() const; bool estáVazia() const; Item const& topo() const; Item& topo(); void põe(Item const& novo_item); void tiraItem(); };

41 2003/2004 Programação Orientada para Objectos 41 Herança privada (III) class PilhaDeInt : private ListaDeInt { public: using ListaDeInt::Item; int altura() const; using ListaInt::estáVazia; Item const& topo() const; Item& topo(); void põe(Item item); void tiraItem(); }; class PilhaDeInt : private ListaDeInt { public: using ListaDeInt::Item; using ListaDeInt::comprimento; using ListaDeInt::estáVazia; using ListaDeInt::trás; using ListaDeInt::põeAtrás; using ListaDeInt::tiraDeTrás; };

42 2003/2004 Programação Orientada para Objectos 42 Conceitos e implementações: relações entre classes Língua naturalC++ Os empregados têm (estão associados a) um chefe. Associação simples: class Empregado { private: Chefe* chefe; }; Uma turma tem (agrega) alunos. Agregação: class Turma { private: list alunos; }; Um humano tem (é composto por) cabeça. Composição: class Humano { private: Cabeça cabeça; }; Não há conceito de posse: tempos de vida independentes Relação possui um: pode implicar o controlo do tempo de vida de um objecto por outro Relação é composto por um: tempos de vida relacionados

43 2003/2004 Programação Orientada para Objectos 43 Aula 7: Sumário 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.


Carregar ppt "1 Aula 7 Herança. 2003/2004 Programação Orientada para Objectos 2 Conceitos fundamentais: Herança Polimorfismo Ligação dinâmica."

Apresentações semelhantes


Anúncios Google