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
Download

7 - iscte-iul