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