Herança Múltipla Polimorfismo
Programação Orientada a Objetos
Tutorial Básico Multi Linguagens
Ronaldo F. Ramos
IFCE
1 de dezembro de 2024
1 / 125
Herança Múltipla Polimorfismo
Conteúdo
1 Herança Múltipla
2 Polimorfismo
2 / 125
Herança Múltipla Polimorfismo
Herança Múltipla
A herança múltipla entre classes ocorre sempre que uma classe derivada possui duas ou
mais classes bases imediatas, ou seja, é “filha” de mais do que uma classe.
Tipicamente, a herança múltipla surge quando características de classes são
combinadas para formar uma única classe.
3 / 125
Herança Múltipla Polimorfismo
Herança Múltipla em C++
Sintaxe:
1 class Nome_ classe : [modificador] classe base1
2 [modificador] class ebase2{
3 // declaracao dos membros
4 };
O modificador default é private. Ex.
1 class D : public A, public C{
2 // declaração dos membros de D
3 };
4 / 125
Herança Múltipla Polimorfismo
Construtores e Destrutores com herança múltipla
Analogamente à herança simples, a classe derivada, pode acessar os construtores de
suas classes base.
Sintaxe:
1 Classe_derivada (atrib.ClassDerivada, atribClasseBase1 ,..., baseN) :
ClasseBase1( atr.class base1), ..., ClasseBasen( atribClasseBaseN ){
2 // função construtora da classe derivada
3 };
Atributos significam os dados da classe. No caso da classe derivada, seus atributos são
aqueles declarados unicamente em seu escopo ( excluem-se os herdados das classes
bases)
5 / 125
Herança Múltipla Polimorfismo
Exemplo em C++ _055_heramult.cpp
1 #include <ncurses.h>
2 #include <cstring >
3 #include <cctype >
4 #include <iostream >
5 /* atenção este programa usa a biblioteca ncurses
6 para instalar usar: sudo apt -get install libncurses5 -dev
libncursesw5 -dev
7 para compilar: g++ -o heramult _055_heramult.cpp -lncurses */
8 const int HORIZ_MAX = 80;
9 const int VERT_MAX = 25;
10 class Horizontal {
11 char tipoh;
12 public:
13 Horizontal(char tipo) : tipoh(tipo) {}
14 int posicao_horizontal (const char* texto);
15 };
6 / 125
Herança Múltipla Polimorfismo
Exemplo em C++ _055_hermult.cpp
16 class Vertical {
17 char tipov;
18 public:
19 Vertical(char tipo) : tipov(tipo) {}
20 int posicao_vertical ();
21 };
22 class Mensagem : public Horizontal, public Vertical {
23 char msg [50];
24 public:
25 Mensagem(const char* texto, char ver, char hor)
26 : Vertical(ver), Horizontal(hor) {
27 strcpy(msg, texto);
28 }
7 / 125
Herança Múltipla Polimorfismo
Exemplo em C++ _055_hermult.cpp
29 void mostrar () {
30 int col = posicao_horizontal (msg);
31 int lin = posicao_vertical ();
32 move(lin, col); // Posiciona o cursor no terminal
33 printw("%s", msg); // Exibe a mensagem
34 refresh ();
35 }
36 };
37 // Implementação das funções de alinhamento horizontal
38 int Horizontal :: posicao_horizontal (const char* texto) {
39 unsigned tam = strlen(texto);
40 switch (tipoh) {
41 case ’C’: return (( HORIZ_MAX - tam) / 2);
42 case ’D’: return (HORIZ_MAX - tam);
43 def ault: return 1;
44 }
45 } 8 / 125
Herança Múltipla Polimorfismo
Exemplo em C++ _055_hermult.cpp
46 // Implementação das funções de alinhamento vertical
47 int Vertical :: posicao_vertical () {
48 switch (tipov) {
49 case ’M’: return (VERT_MAX / 2);
50 case ’R’: return VERT_MAX - 1; // Ajustado para índice 0-base
51 def ault: return 1;
52 }
53 }
9 / 125
Herança Múltipla Polimorfismo
Exemplo em C++ _055_hermult.cpp
54 int main () {
55 char texto [50], hor, ver;
56 // Inicializa ncurses
57 initscr ();
58 noecho ();
59 cbreak ();
60 do {
61 clear ();
62 mvprintw (2, 10, "Entre com o Texto: ");
63 echo ();
64 getnstr(texto, 50); // Entrada de texto
65 noecho ();
10 / 125
Herança Múltipla Polimorfismo
Exemplo em C++ _055_hermult.cpp
66 // Alinhamento Horizontal
67 do {
68 clear ();
69 mvprintw (2, 10, "Alinhamento Horizontal:");
70 mvprintw (4, 10, "(E)squerdat(C)entradot(D)ireita:");
71 hor = toupper(getch ());
72 } while (hor != ’E’ && hor != ’C’ && hor != ’D’);
73 // Alinhamento Vertical
74 do {
75 clear ();
76 mvprintw (5, 10, "Alinhamento Vertical:");
77 mvprintw (7, 10, "(T)opott(M)eiott(R)oda -pe:");
78 ver = toupper(getch ());
79 } while (ver != ’T’ && ver != ’M’ && ver != ’R’);
11 / 125
Herança Múltipla Polimorfismo
Exemplo em C++ _055_hermult.cpp
80 // Exibir mensagem
81 Mensagem tela(texto, ver, hor);
82 clear ();
83 tela.mostrar ();
84 getch ();
85 // Pergunta de continuação
86 clear ();
87 mvprintw (10, 10, "Deseja continuar? (S/N):");
88 } while (toupper(getch ()) == ’S’);
89 // Finaliza ncurses
90 endwin ();
91 return 0;
92 }
12 / 125
Herança Múltipla Polimorfismo
Ambiguidades
A ambiguidade corre quando as classes base possuem membros homônimos não
existentes na classe derivada. Quando um objeto da classe derivada tentar referenciar
este membro homônimo das classes base, o compilador não reconhecerá a qual classe
está se referindo.
13 / 125
Herança Múltipla Polimorfismo
Exemplo de Ambiguidades em C++
1 class Surf{
2 float notas [10]; // ordem decrescente de notas
3 public:
4 void ordena ();
5 };
6 class Vela{
7 float tempos [10];
8 public:
9 void ordena (); // ordem crescente de tempos
10 }
11 class WIndSurf : public Surf, public Vela{
12 char competicao;
13 };
14 / 125
Herança Múltipla Polimorfismo
Problema 1
Caso um objeto da classe WindSurf fosse criado e tentasse utilizar a função ordena()
de uma classe base haveria uma ambiguidade detectada pelo compilador.
1 void main (){
2 WindSurf corrida;
3 corrida.ordena ();// erro de ambiguidade
4 }
15 / 125
Herança Múltipla Polimorfismo
Solução 1
1 class WindSurf :public Surf, public Vela{
2 char competicao;
3 public:
4 void ordena (){
5 if(competicao ==’E’)
6 Surf :: Ordena ();
7 else
8 Vela :: ordena ();
9 }
10 }
16 / 125
Herança Múltipla Polimorfismo
Ambiguidades - problema 2 (Problema do Diamante)
Um segundo tipo de ambiguidades que pode ocorrer, refere-se a uma particularidade
da hierarquia das classes em herança múltipla.
Suponha um programa onde simplesmente imprime-se um valor de um atributo
da classe Classe A (o string Nome), uma vez através da classe B1 e outra através
da classe B2, cujas inicializações seguem valores default diferentes.
class ClasseB1 : public ClasseA...;
class ClasseB2: public ClasseA...;
class ClasseC : public ClasseB1,
public ClasseB2 .. ;
17 / 125
Herança Múltipla Polimorfismo
Exemplo de Ambiguidade na Herança Múltipla _056_diamante.cpp
1 // VIRTDUP.CPP - Duplicidade em super classe na Herança Multipla
2 #include <iostream >
3 #include <string > // Para usar string
4 using namespace std;
5 class ClasseA {
6 protected:
7 string nome;
8 public:
9 void mostrar () const {
10 cout << "nNome na Classet t: " << nome;
11 }
12 };
18 / 125
Herança Múltipla Polimorfismo
Exemplo de Ambiguidade na Herança Múltipla _056_diamante.cpp
13 class ClasseB1 : public ClasseA {
14 public:
15 ClasseB1(const string& n = "ClasseB1") {
16 nome = n;
17 }
18 void mostrar () const {
19 ClasseA :: mostrar ();
20 }
21 };
19 / 125
Herança Múltipla Polimorfismo
Exemplo de Ambiguidade na Herança Múltipla _056_diamante.cpp
22 class ClasseB2 : public ClasseA {
23 public:
24 ClasseB2(const string& n = "ClasseB2") {
25 nome = n;
26 }
27 void mostrar () const {
28 ClasseA :: mostrar ();
29 }
30 };
20 / 125
Herança Múltipla Polimorfismo
Exemplo de Ambiguidade na Herança Múltipla _056_diamante.cpp
31 class ClasseC : public ClasseB1, public ClasseB2 {
32 public:
33 void mostrar () const {
34 ClasseB1 :: mostrar ();
35 ClasseB2 :: mostrar ();
36 }
37 };
38 int main () {
39 ClasseC objetoClasseC;
40 objetoClasseC.mostrar ();
41 cout << "n";
21 / 125
Herança Múltipla Polimorfismo
Exemplo de Ambiguidade na Herança Múltipla _056_diamante.cpp
O membro nome possui dois valores simultâneos, "ClasseB1"e "Classe B2". Na
realidade há duas instâncias de superclasse: uma é alcançada pelo caminho
ClasseC-ClasseB1-ClasseA e a outra pelo caminho ClasseC-ClasseB2-ClasseA.
A solução portanto seria especificar o nome da classe mãe para chamar a função
específica, porem erros de acesso a variáveis também podem ocorrer:
1 class ClasseC : public ClasseB1,public ClasseB2{
2 public:
3 void mostrar (){
4 strcpy(nome,"ObjetoClasseC"); // erro ambiguidade.
5 ClasseB1 :: mostrar ();
6 ClasseB2 :: mostrar ();
7 }
8 }
22 / 125
Herança Múltipla Polimorfismo
Problema dos Construtores
1 class A {
2 public:
3 A() { cout << "Construtor de An"; }
4 };
5 class B1 : public A {
6 public:
7 B1() { cout << "Construtor de B1n"; }
8 };
9 class B2 : public A {
10 public:
11 B2() { cout << "Construtor de B2n"; }
12 };
13 class C : public B1, public B2 {
14 public:
15 C() { cout << "Construtor de Cn"; }
16 };
23 / 125
Herança Múltipla Polimorfismo
Problema dos Construtores
1 int main () {
2 C obj; // qual construtor será executado ??
3 return 0;
4 }
• Ao criar um objeto da classe C, qual construtor de A será chamado?
• Como B1 e B2 herdam de A, há duas cópias independentes da classe base A.
• O compilador não saberá qual caminho seguir, causando um erro.
24 / 125
Herança Múltipla Polimorfismo
Problema dos Construtores
1 int main () {
2 C obj; // qual construtor será executado ??
3 return 0;
4 }
• Ao criar um objeto da classe C, qual construtor de A será chamado?
• Como B1 e B2 herdam de A, há duas cópias independentes da classe base A.
• O compilador não saberá qual caminho seguir, causando um erro.
24 / 125
Herança Múltipla Polimorfismo
Solução Usando Classes Bases Virtuais
• Use a palavra-chave virtual para compartilhar a classe base entre as classes
derivadas.
• A herança virtual garante que apenas uma instância da classe base (A) seja
compartilhada entre as classes derivadas (B1 e B2).
• Resolve o problema de ambiguidade.
25 / 125
Herança Múltipla Polimorfismo
Corrigindo o código
1 class A {
2 public:
3 A() { cout << "Construtor de An"; }
4 };
5 class B1 : virtual public A {
6 public:
7 B1() { cout << "Construtor de B1n"; }
8 };
9 class B2 : virtual public A {
10 public:
11 B2() { cout << "Construtor de B2n"; }
12 };
13 class C : public B1, public B2 {
14 public:
15 C() { cout << "Construtor de Cn"; }
16 };
26 / 125
Herança Múltipla Polimorfismo
Classes Bases Virtuais
No estudo de membros estáticos em classes, viu-se que todos os objetos da classe
compartilham o mesmo membro quando este é estático. Em uma analogia, a classe
base virtual provoca o mesmo efeito para as instâncias superiores na hierarquia da
herança múltipla.
27 / 125
Herança Múltipla Polimorfismo
Sintaxe da Definição de Classes Bases Virtuais
1 class Classe_Derivada : [modificador] virtual ClasseBase{...}
28 / 125
Herança Múltipla Polimorfismo
Solução para o Programa Acima
1 class ClasseB1 : public virtual ClasseA{
2 public:
3 ClasseB1 (char * n = "ClasseB1"){ strcpy(nome,n);}
4 void mostrar (){ClasseA :: mostrar ();}
5 }
6 class ClasseB2 : public virtual ClasseA{
7 public:
8 ClasseB2 (char * n = "ClasseB2"){ strcpy(nome,n);}
9 void mostrar (){ClasseA :: mostrar ();}
10 }
29 / 125
Herança Múltipla Polimorfismo
Restrição
• Classes bases virtuais não podem ter construtores com parâmetros.
30 / 125
Herança Múltipla Polimorfismo
Exemplo de Aplicação
Seja um programa cujo objetivo é o de contabilizar as despesas de uma pessoa com
seu prédio. Os gastos do prédio referem-se ao condomínio e às despesas gerais do
edifício, pagos por moradores e proprietários, respectivamente. Um morador que é
dono do seu apartamento terá os dois tipos de gastos.
31 / 125
Herança Múltipla Polimorfismo
Exemplo de Aplicação - 2
Assim uma pessoa para a qual se deseja contabilizar os gastos estará em uma destas
três categorias:
1 class Pessoa{ char nome [31]; }
2 class Morador : public virtual Pessoa{...}
3 class Proprietario: public virtual Pessoa{..}
4 class Morador_proprietario : public Morador, public Proprietario{..}
32 / 125
Herança Múltipla Polimorfismo
Exemplo Completo Usando Classes Bases Virtuais _057_virtual.cpp
1 // virtclas.cpp - Exemplo com Classes Virtuais em C++
2 #include <iostream >
3 #include <cstring >
4 using namespace std;
5 class Pessoa {
6 protected:
7 char nome [31];
8 public:
9 void mostrar () {
10 cout << "nNome do Condômino: " << nome << endl;
11 }
12 };
33 / 125
Herança Múltipla Polimorfismo
Exemplo Completo Usando Classes Bases Virtuais _057_virtual.cpp
13 class Morador : virtual public Pessoa {
14 protected:
15 float condominio;
16 public:
17 Morador(const char* nome_mor, float cond) {
18 strncpy(nome, nome_mor, sizeof(nome) - 1);
19 nome[sizeof(nome) - 1] = ’0’; // Garante terminação segura
20 condominio = cond;
21 }
22 };
34 / 125
Herança Múltipla Polimorfismo
Exemplo Completo Usando Classes Bases Virtuais _057_virtual.cpp
23 class Proprietario : virtual public Pessoa {
24 protected:
25 float despesas;
26 public:
27 Proprietario(const char* nome_prop, float gastos) {
28 strncpy(nome, nome_prop, sizeof(nome) - 1);
29 nome[sizeof(nome) - 1] = ’0’; // Garante terminação segura
30 despesas = gastos;
31 }
32 };
35 / 125
Herança Múltipla Polimorfismo
Exemplo Completo Usando Classes Bases Virtuais _057_virtual.cpp
33 class Morador_proprietario : public Morador, public Proprietario {
34 public:
35 Morador_proprietario (const char* nome_mp, float cond, float
gastos)
36 : Morador(nome_mp, cond), Proprietario(nome_mp, gastos) {
37 strncpy(nome, nome_mp, sizeof(nome) - 1);
38 nome[sizeof(nome) - 1] = ’0’; // Garante terminação segura
39 }
40 void mostrar_ () {
41 mostrar (); // chamada ambígua sem a classe virtual porque a
classe derivada terá duas cópias das duas
42 // class es bases respectivamente
43 cout << "Condomínio: R$ " << condominio << endl;
44 cout << "Despesas: R$ " << despesas << endl;
45 }
46 };
36 / 125
Herança Múltipla Polimorfismo
Exemplo Completo Usando Classes Bases Virtuais _057_virtual.cpp
47 int main () {
48 // Exemplo de uso
49 Morador_proprietario mp("João Silva", 800.50, 1200.75);
50 mp.mostrar_ ();
51 return 0;
52 }
37 / 125
Herança Múltipla Polimorfismo
Resultado
Caso a classe base pessoa não fosse declarada como virtual nas heranças de
Proprietário e Morador, ocorreria um erro de ambiguidade.
1 void Morador_proprietario :: mostrar(void){
2 mostrar () // ambiguidade de caminhos
3 ...
4 }
O erro apontado pelo compilador seria o seguinte: "member is
ambiguous:’Pessoa::mostrar’ and ’Pessoa::Mostrar’"O compilador não sabe qual o
caminho a tomar até a raiz, se passando pela classe Morador ou pela classe
Proprietário.
38 / 125
Herança Múltipla Polimorfismo
Herança Múltipla em JAVA
A linguagem Java não implementa a herança múltipla, mas podemos usar algo
parecido usando interfaces.
39 / 125
Herança Múltipla Polimorfismo
Interfaces como Solução
• Interfaces permitem múltiplas heranças sem ambiguidades:
• Uma classe pode implementar várias interfaces.
• Cada interface define apenas contratos (métodos abstratos) (Sem
implementação).
• A implementação é responsabilidade da classe que as implementa.
40 / 125
Herança Múltipla Polimorfismo
Exemplo de Uso de Interfaces
Definindo interfaces:
1 interface Animal {
2 void comer ();
3 }
4 interface Passaro {
5 void voar ();
6 }
Implementando interfaces:
1 class Bat implements Animal, Passaro {
2 public void comer () {
3 System.out.println("Comento...");
4 }
5 public void voar () {
6 System.out.println("Voando...");
7 }
8 } 41 / 125
Herança Múltipla Polimorfismo
Vantagens do Uso de Interfaces
• Evita ambiguidade da herança múltipla.
• Promove maior flexibilidade e modularidade.
• Permite a criação de classes altamente coesas e de fácil manutenção.
42 / 125
Herança Múltipla Polimorfismo
Desvantagens do Uso de Interfaces
• Implementações obrigatórias nas classes derivadas
• Ausência de Estado Compartilhado
• Complexidade Crescente com Interfaces Múltiplas
43 / 125
Herança Múltipla Polimorfismo
Implementação Obrigatória de Métodos/Métodos Default
• Interfaces podem incluir métodos default (a partir do Java 8), que oferecem uma
implementação padrão.
• Nesse caso, a classe que implementa a interface não é obrigada a sobrescrever
esses métodos.
• No entanto, os métodos abstratos ainda precisam ser implementados.
44 / 125
Herança Múltipla Polimorfismo
Exemplo de Métodos Default
1 interface Animal {
2 void comer ();
3 def ault void dormir () {
4 System.out.println("Animal dormindo");
5 }
6 }
7 class Cachorro implements Animal {
8 @Override
9 public void comer () {
10 System.out.println("Cachorro comendo");
11 }
12 // dormir () não precisa ser implementado, pois já tem uma
implementação padrão.
13 }
45 / 125
Herança Múltipla Polimorfismo
Exemplo Cliente Funcionário em JAVA _058_interfaces.java
1 //
2 // Programa cliente_funcionario .java - Ilustra a utilização
3 // de interfaces
4 //
5 interface cliente{
6 float qualquer = 0;
7 float calcula_renda_liquida (float bruta);
8 }
9 class funcionario{
10 String Nome = "Ze dos Moveis";
11 String Setor = "Carpintaria";
12 String Cargo = "Marcineiro";
13 float SalarioBruto = 120.00f;
14 }
46 / 125
Herança Múltipla Polimorfismo
Exemplo Cliente Funcionário em JAVA _058_interfaces.java
15 class cliente_funcionario extends funcionario implements cliente{
16 public float calcula_renda_liquida (float bruta){
17 return 0.75f*bruta;
18 }
19 void mostra_dados (){
20 System.out.println("Nome "+Nome);
21 System.out.println("Setor "+Setor);
22 System.out.println("Cargo "+Cargo);
23 System.out.println("Renda
liquida"+ calcula_renda_liquida (SalarioBruto));
24 }
25
26 }
47 / 125
Herança Múltipla Polimorfismo
Exemplo Cliente Funcionário em JAVA _058_interfaces.java
27 public class _058_interfaces {
28 static public void main(String Args []){
29 cliente_funcionario cf = new cliente_funcionario ();
30 cf.mostra_dados ();
31 }
32 }
48 / 125
Herança Múltipla Polimorfismo
Herança Múltipla em Python _059_pessoa.py
Observemos classe Pessoa abaixo.
1 class Pessoa:
2 def __init__(self,nome,end,fone):
3 print("Executando Costrutor de Pessoa ")
4 self.nome,self.endereco,self.telefone = nome,end,fone
5 def __str__(self):
6 return "NOME: "+self.nome+" END. "+self.endereco+" FONE:
"+self.telefone
49 / 125
Herança Múltipla Polimorfismo
Herança Múltipla _060_estudante.py
E agora a classe Estudante.
1 from pessoa import *
2 class Estudante(Pessoa):
3 listaEstudantes = []
4 def __init__(self,nome,end,fone,curso,periodo):
5 print("Executando o construtor de Estudante ")
6 Pessoa.__init__(self, nome,end,fone)
7 self.curso = curso
8 self.periodo = periodo
9 Estudante. listaEstudantes .append(self)
10
11 def calculaIra(self):
12 return 0
50 / 125
Herança Múltipla Polimorfismo
Herança Múltipla _061_professor.py
E agora a classe Professor.
1 from pessoa import *
2 class Professor(Pessoa):
3 listaProfessores = []
4 def __init__(self,nome,end,fone,listaCursos):
5 print("Executando o construtor de Professor ")
6 Pessoa.__init__(self, nome,end,fone)
7 self.listaCursos = listaCursos
8 Professor. listaProfessores .append(self)
9
10 def calculaCargaHoraria (self):
11 return 0
51 / 125
Herança Múltipla Polimorfismo
Herança Múltipla _062_estagiario.py
Agora imagine um aluno que também é professor. Uma espécie de estagiário de ensino.
1 from estudante import *
2 from professor import *
3 class EstagiarioEnsino (Estudante,Professor):
4 def
__init__(self,nome,end,fone,curso,periodo,listaCursos, duracaoEstagio
5 print("Iniciando construtor de estagiário ")
6 Estudante.__init__(self, nome, end, fone, curso, periodo)
7 Professor.__init__(self, nome, end, fone, listaCursos)
8 self.duracaoEstagio = duracaoEstagio
52 / 125
Herança Múltipla Polimorfismo
Herança Múltipla _063_usaEstagiario.py
Agora vamos usar tudo.
1 from estagiario import *
2 def main ():
3 print("Atenção para a ordem de chamada dos construtores ")
4 st = EstagiarioEnsino ("Pedro","Rua das Acacias 43",
"98213344","Mecânica",6,["logica","Programação"],24)
5 print("Estagiário criado")
6
7 if __name__ =="__main__":
8 main ()
53 / 125
Herança Múltipla Polimorfismo
Herança Múltipla
Saída:
54 / 125
Herança Múltipla Polimorfismo
Revisando O Problema do Diamante
55 / 125
Herança Múltipla Polimorfismo
Vejamos algumas modificações no código anterior.Classe Estudante
_064_estudanteModificado.py
1 from pessoa import *
2 class Estudante(Pessoa):
3 listaEstudantes = []
4 def __init__(self,nome,end,fone,curso,periodo):
5 print("Executando o construtor de Estudante ")
6 super ().__init__(self,nome,end,fone)
7 self.curso = curso
8 self.periodo = periodo
9
10 def calculaIra(self):
11 return 0
56 / 125
Herança Múltipla Polimorfismo
Classe Professor. _065_professorModificado.py
1 from pessoa import *
2 class Professor(Pessoa):
3 listaProfessores = []
4 def __init__(self,nome,end,fone,listaCursos):
5 print("Executando o construtor de Professor ")
6 super ().__init__(nome,end,fone)
7 self.listaCursos = listaCursos
8
9 def calculaCargaHoraria (self):
10 return 0
57 / 125
Herança Múltipla Polimorfismo
Classe Estagiário. _066_estagiarioModificado.py
1 from estudanteModificado import *
2 from professorModificado import *
3 class EstagiarioEnsino (Estudante,Professor):
4 def
__init__(self,nome,end,fone,curso,periodo,listaCursos, duracaoEstagio
5 print("Iniciando construtor de estagiário ")
6 super ().__init__(nome, end, fone, curso, periodo)
7 self.duracaoEstagio = duracaoEstagio
58 / 125
Herança Múltipla Polimorfismo
Finalmente usando tudo. _067_herancaMultiplaSuper.py
1 from pessoa import *
2 from estudanteModificado import *
3 from professorModificado import *
4 from estagiarioModificado import *
5
6 def main ():
7 print("Atenção para a ordem de chamada dos construtores ")
8 st = EstagiarioEnsino ("Pedro","Rua das Acacias 43",
"98213344","Mecânica",6,["logica","Programação"],24)
9 print("Estagiário criado")
10
11 if __name__ =="__main__":
12 main ()
59 / 125
Herança Múltipla Polimorfismo
Saída ...
Isso ocorre devido ao algoritmo e MRO (method resolution order). Ver documentação.
60 / 125
Herança Múltipla Polimorfismo
Method Resolution Order
O Method Resolution Order (MRO) em Python determina a ordem na qual as classes
são pesquisadas para encontrar um método ou atributo quando é feita uma chamada.
Ele é crucial para a herança múltipla, pois define a sequência de classes que serão
consultadas. Essa ordem é baseada no algoritmo C3 Linearization, que garante uma
hierarquia consistente e previsível.
61 / 125
Herança Múltipla Polimorfismo
Funcionamento do MRO
Busca em Profundidade Linearizada (C3 Linearization):
• O MRO combina a ordem linear de herança das classes (em profundidade) com a
ordem em que elas aparecem na definição de uma classe.
• O algoritmo garante que:
• Um método ou atributo em uma classe superior não seja sobrescrito por
classes subordinadas de forma inconsistente. 1
• A hierarquia respeite a precedência declarada na herança múltipla.
1
Resolve o problema da ambiguidade
62 / 125
Herança Múltipla Polimorfismo
Regra Básica MRO
Python busca métodos/atributos em:
• A própria classe.
• Suas classes-mãe (da esquerda para a direita na declaração de herança).
• Classes ascendentes até o topo da hierarquia, que é sempre object
63 / 125
Herança Múltipla Polimorfismo
Exercício
Mude a ordem da herança das classes acima e veja o que acontece com a chamada dos
construtores.
64 / 125
Herança Múltipla Polimorfismo
ATENÇÃO. Probleminha com argumentos.
Os argumentos mudam ao chamar funções da classe mãe pela classe ou pela função
super()
Pessoa.__init__(self,nome,end,fone)
super().__init__(nome,end,fone)
As classes mães podem ter listas de argumentos diferentes. Como quem decide é o
compilador, poderemos ter problemas.
Classe Estudante:
def __init__(self,nome,end,fone,curso,periodo):
˙
..
Classe Professor:
def __init__(self,nome,end,fone,listaCursos):
65 / 125
Herança Múltipla Polimorfismo
Solução: Sobrecarga?? Argumentos Flexíveis
Python usa argumentos flexíveis de várias formas.
• Tipos e Retorno dinâmicos (Duck Typing)
def calcula(a,b):
.̇.
calcula(3,4)
• Argumentos default
def calcula(a=1,b=3,c="maria"):
.̇.
calcula(1)
calcula(1,2)
calcula(1,2,"pedro")
.̇
• Listas de argumentos
def calcula(*list):
66 / 125
Herança Múltipla Polimorfismo
Listas de Argumentos _068_lstaArgumentosSimples.py
Observe a definição da função calcula(*lista). O operador * em lista implica que o
compilador aceitará qualquer lista de argumentos e colocará em uma lista de strings de
nome lista.
1 def imprimeArgs (* args):
2 print("nLista de argumentos:",end="")
3 for a in args: print(a,end=",")
4 def main ():
5 imprimeArgs ()
6 imprimeArgs("Uma String")
7 imprimeArgs (23)
8 imprimeArgs("Uma string",2,"Segunda String",[1,2,3,4]," e muito
mais")
9 if __name__ =="__main__":
10 main ()
67 / 125
Herança Múltipla Polimorfismo
Listas de Argumentos - Saída
Observe a saída do programa anterior.
Lista de argumentos:
Lista de argumentos:Uma String,
Lista de argumentos:23,
Lista de argumentos:Uma string,2,Segunda String,[1, 2, 3, 4], e muito mais,
68 / 125
Herança Múltipla Polimorfismo
Listas de Argumentos _069_listaArgumentosDicionario.py
O duplo ** nos remete a criação de uma estrutura de dados chamada dicionário. Veja.
1 def imprimeArgs (** kwargs):
2 print(kwargs)
3
4 if __name__ =="__main__":
5 imprimeArgs(nome="maria",idade =25,estadoCivil="solteira")
Saída.
{’nome’: ’maria’, ’idade’: 25, ’estadoCivil’: ’solteira’}
69 / 125
Herança Múltipla Polimorfismo
Listas de Argumentos _070_listaArgumentosDicionarios2.py
Trabalhando um pouco os argumentos
1 def imprimeArgs (** kwargs):
2 for rotulo,valor in kwargs.items ():
3 print("%s = %s"%( rotulo, valor))
4 if __name__ =="__main__":
5 imprimeArgs(nome="maria",idade =25,estadoCivil="solteira")
Saída.
idade = 25
estadoCivil = solteira
nome = maria
70 / 125
Herança Múltipla Polimorfismo
Polimorfismo
Conceito que permite que diferentes classes respondam a chamadas de métodos ou
operadores com o mesmo nome, mas com comportamentos específicos para cada
classe. O termo vem do grego e significa "muitas formas". Pode ser implementado
através de:
• Sobrecarga de métodos
• Sobrecarga de operadores
• Sobrescrita de métodos
• implementação de interfaces
71 / 125
Herança Múltipla Polimorfismo
Polimorfismo em C++ Via Função Virtual
• O conceito de polimorfismo dá caráter sintético aos programas. Em uma
hierarquia, a semelhança de funções pode ocorrer nos diferentes níveis. Por
exemplo, pode-se utilizar uma função gravar() para apresentar os membros dos
objetos de cada classe na hierarquia.
• Com a sobrecarga, poder-se-ia criar uma função gravar() para cada classe e
diferenciar-se as mesmas pelo operador de resolução de escopo(::).
• O polimorfismo em hierarquias de classes tem uma forma de implementação mais
eficiente quando são utilizadas as funções virtuais.
72 / 125
Herança Múltipla Polimorfismo
Sintaxe Funções Virtuais
1 class ClasseBase{
2 virtual Protótipo_função_virtual ();
3 };
4 class ClasseDerivada :: ClasseBase{
5 [virtual] Protótipo_função_virtual ();
6 };
73 / 125
Herança Múltipla Polimorfismo
Exemplo Polimorfismo via Função Virtual _071_funcvirt.cpp
1 // FUNCVIRT.CPP - Programa Exemplificando o Uso de Funções Virtuais
2 #include <iostream >
3 #include <string >
4 #include <limits >
5 using namespace std;
6 class Transacao {
7 protected:
8 string cliente;
9 public:
10 Transacao(const string& nome) : cliente(nome) {}
11 virtual void mostrar () {
12 cout << "Nome do Cliente : " << cliente << ’n’;
13 }
14 virtual ~Transacao () {} // Destrutor virtual para garantir
limpeza correta
15 };
74 / 125
Herança Múltipla Polimorfismo
Exemplo Polimorfismo via Função Virtual _071_funcvirt.cpp
16 class Venda_Vista : public Transacao {
17 protected:
18 double valor;
19 public:
20 Venda_Vista(const string& nome, double preco)
21 : Transacao(nome), valor(preco) {}
22 void mostrar () override {
23 Transacao :: mostrar ();
24 cout << "Valor da Compra : " << valor << ’n’;
25 }
26 };
75 / 125
Herança Múltipla Polimorfismo
Exemplo Polimorfismo via Função Virtual _071_funcvirt.cpp
27 };
28 class Venda_Prazo : public Venda_Vista {
29 float juros;
30 public:
31 Venda_Prazo(const string& nome, double preco, float taxa)
32 : Venda_Vista(nome, preco), juros(taxa) {}
33 void mostrar () override {
34 Transacao :: mostrar ();
35 cout << "Taxa Praticada : " << juros << "%n";
36 cout << "Valor da Compra : " << valor * (100 + juros) / 100
<< ’n’;
37 }
38 };
76 / 125
Herança Múltipla Polimorfismo
Exemplo Polimorfismo via Função Virtual _071_funcvirt.cpp
39 int main () {
40 string nome;
41 double preco;
42 float taxa;
43 cout << "Entre com o Nome: ";
44 getline(cin, nome);
45 cout << "Entre com o Valor a Vista: ";
46 cin >> preco;
47 cout << "Entre com a Taxa de Juros (%): ";
48 cin >> taxa;
49 // Usando ponteiros brutos
77 / 125
Herança Múltipla Polimorfismo
Exemplo Polimorfismo via Função Virtual _071_funcvirt.cpp
50 Transacao* vendas [3];
51 vendas [0] = new Transacao(nome);
52 vendas [1] = new Venda_Vista(nome, preco); // chamada polimorfica
53 vendas [2] = new Venda_Prazo(nome, preco, taxa); // idem
54 cout << "nn";
55 for (int i = 0; i < 3; i++) {
56 vendas[i]->mostrar ();
57 cout << ’n’;
58 }
78 / 125
Herança Múltipla Polimorfismo
Exemplo Polimorfismo via Função Virtual _071_funcvirt.cpp
59 // Liberando memória manualmente
60 for (int i = 0; i < 3; i++) {
61 delete vendas[i];
62 }
63 // Espera o usuário antes de encerrar o programa
64 cout << "Pressione Enter para sair...";
65 // descarta caracteres do buffer de entrada
66 //
67 cin.ignore ();
68 cin.get();
69 return 0;
70 }
79 / 125
Herança Múltipla Polimorfismo
Porque usar Função Virtual
• Sem a palavra-chave virtual, o método chamado seria determinado com base no
tipo do ponteiro ou referência, não no tipo real do objeto. Isso é chamado de
ligação estática (ou early binding), o que não é desejado em muitos casos de
herança.
• Com virtual, o método chamado é determinado pelo tipo real do objeto apontado
pelo ponteiro ou referência (ligação dinâmica ou late binding). Isso permite que o
comportamento correto seja executado para objetos das classes derivadas.
80 / 125
Herança Múltipla Polimorfismo
Exercício
É conveniente compararmos o resultado do programa com a simples remoção da
palavra virtual da declaração da função mostrar() da classe base Transação. Neste
caso o resultado do programa seria:
Nome do cliente : nome
Nome do cliente : nome
Nome do cliente : nome
81 / 125
Herança Múltipla Polimorfismo
Explicação
A razão está no fato de quando mostrar deixa de ser virtual, o compilador não
associará sua chamada ao tipo de objeto que a faz. Com a função virtual o compilador
decide em tempo de execução , qual o tipo de objeto que está chamando a função
mostrar().Isto ocorre no momento das atribuições:
vendas[0] = new Transacao(nome);
vendas[1] = new Venda_Vista(nome,preco);
vendas[2] = new Venda_Prazo(nome,preco,taxa);
Uma chamada a vendas[2]->mostrar() chamará Vendas_Prazo::mostrar() e não
Transacao::mostrar().
82 / 125
Herança Múltipla Polimorfismo
Alternativa Usando Referências
Uma alternativa a esta implementação é a utilização de referências à classe base
transação. Para tal o programa receberia as seguintes modificações na função main():
1 void main (){
2 ...
3 Trasacao ObjTransacao(nome); // objeto da base
4 Venda_Vista objVenda_Vista(nome, preco);// derivada
5 Venda_Prazo objVenda_Prazo(nome,preco,taxa); // idem
6 Transacao & vendas1 = objTransacao; // refere.
7 Transacao & vendas2 = objVenda_vista;
8 Transacao & vendas3 = objVenda_Prazo;
9 ...
10 }
Pense em algo mais elegante.
83 / 125
Herança Múltipla Polimorfismo
Restrições
• A função deve ser declarada como virtual na classe base caso contrário o
compilador entenderá que a classe na qual a função aparece deverá ter herdeiras
com esta função.
• A função virtual deve estar definida na classe base, mesmo sem código algum.
• Os protótipos de funções virtuais nas classes derivadas devem ser idênticos ao
protótipo da classe base. Caso contrário ocorrerá sobrecarga de funções.
• Construtores não podem ser funções virtuais.Pelo fato de que cosntrutores não
são herdados. Já destrutores não só é possível como útil.
• Caso o modificador de herança não seja public não se poderá criar uma referência
para acesso à classe privada via base. Erro de conversão.
84 / 125
Herança Múltipla Polimorfismo
Exemplos de Erros
1 class ClasseBase {
2 public :
3 virtual void funcao_virtual () {
4 cout << "Esta e’ a ClasseBase !!n";
5 }
6 };
7 // B) ERRO - NAO DEFINIR A FUNCAO VIRTUAL PARA A CLASSE BASE
8 // void funcao_virtual ();}; // so’ declarada
9 // C) WARNING - USAR PROTOTIPOS DIFERENTES P/ A FUNCAO VIRTUAL.
10 // virtual void funcao_virtual (char * msg) {
11 // cout << msg << "n";}};
12 // Warning :’ClasseDerivada :: prototipo1_funcao_virtual ()’ hides
virtual
13 // function ’ClasseBase :: prototipo2_funcao_virtual ()’
14 // D) ERRO - CONSTRUTOR VIRTUAL
15 // virtual ClasseBase () {
16 // cout << "Construcao da ClasseBase ";}}; 85 / 125
Herança Múltipla Polimorfismo
Destrutores Virtuais
• Destrutores definidos também para as classes derivadas, é aconselhável definí-los
como virtual.
• Estes não causam problemas quando apenas objetos na hierarquia são definidos.
Porém caso algum objeto derivado seja criado através de ponteiro para a classe
base , certamente o funcionamento dos destrutores sobrecarregados causará
problemas ao programa.
86 / 125
Herança Múltipla Polimorfismo
Destrutores Virtuais
Observando o programa a seguir verifica-se que apenas o destrutor da classe base
Pessoa foi chamado na execução do comando delete ptrPessoa. da função main().
Com isso o programa deixou de desalocar a memória dinâmica reservada para
informações adicionais( atributo informações da classe referência) e não gravaria as
referências dadas pelo usuário.
87 / 125
Herança Múltipla Polimorfismo
Destrutores Virtuais - Cont - _072_desvirt.cpp
1 #include <iostream >
2 #include <cstring >
3 #include <cctype >
4 using namespace std;
5 char newline, confirma;
6 class Pessoa {
7 protected:
8 char* nome;
9 private:
10 char telefone [13];
11 public:
12 Pessoa(char*, char *);
13 virtual ~Pessoa (); // Destrutor virtual
14 };
88 / 125
Herança Múltipla Polimorfismo
Destrutores Virtuais - Cont _072_desvirt.cpp
15 class Referencias : public Pessoa {
16 char* infor macoes;
17 public:
18 Referencias(char*, char *);
19 ~Referencias ();
20 };
21 int main () {
22 while (1) {
23 char nom [31], fone [13];
24 Pessoa* ptrPessoa;
25 cout << "DADOS PESSOAIS : " << endl;
26 cout << "Nome : ";
27 cin.getline(nom, 30);
89 / 125
Herança Múltipla Polimorfismo
Destrutores Virtuais - Cont _072_desvirt.cpp
28 cout << "Telefone : ";
29 cin.getline(fone, 12);
30 cout << "nDeseja Anotar Referencias sobre a Pessoa (S/N) ??
" << flush;
31 cin.get(confirma);
32 cin.get(newline);
33 if (( toupper(confirma) != ’S’) && (confirma != ’n’))
34 ptrPessoa = new Pessoa(nom, fone);
35 else
36 ptrPessoa = new Referencias(nom, fone);
37 delete ptrPessoa;
38 cout << "nnDeseja Continuar : (S/N) ";
90 / 125
Herança Múltipla Polimorfismo
Destrutores Virtuais - Cont _072_desvirt.cpp
39 cin.get(confirma);
40 cin.get(newline);
41 if (toupper(confirma) != ’S’) break;
42 }
43 return 0;
44 }
45 Pessoa :: Pessoa(char* nom, char* fone) {
46 nome = new char[strlen(nom) + 1];
47 strcpy(nome, nom);
48 strcpy(telefone, fone);
49 }
50 Pessoa ::~ Pessoa () {
51 cout << "nGravando Nome e Telefone de " << nome << " ..." <<
endl;
52 delete [] nome;
53 // Deve -se implementar a gravação em arquivo
54 } 91 / 125
Herança Múltipla Polimorfismo
Destrutores Virtuais - Cont _072_desvirt.cpp
55 Referencias :: Referencias(char* nom, char* fone) : Pessoa(nom, fone) {
56 char aux [300];
57 cout << "nnnREFERENCIAS SOBRE " << nome << " : nn";
58 cin.getline(aux, 300);
59 infor macoes = new char[strlen(aux) + 1];
60 strcpy(infor macoes, aux);
61 }
62 Referencias ::~ Referencias () {
63 cout << "Destruindo a classe derivada"<<endl;
64 cout << "nnGravando Infor macoes sobre " << nome << " ..." <<
endl;
65 delete [] infor macoes;
66 }
92 / 125
Herança Múltipla Polimorfismo
Soluções Cabíveis
• Criação direta do objeto: Referencias objReferencia(nom,fone);
• Criação de um ponteiro para a classe derivada Referencias: Referencias *
ptrReferencias = new Referencias(nom,fone);
• No programa anterior para continuar usando o ponteiro para a classe base na
criação de objetos de ambas as classes na hierarquia, o destrutor desta classe deve
ser declarado como virtual. : virtual Pessoa()
93 / 125
Herança Múltipla Polimorfismo
Classes Abstratas e Funções Virtuais Puras
• Em C++ as classes que não possuem objetos são denominadas classes abstratas.
Nestes tipos de classe não há definição para o código de pelo menos uma de suas
funções, ficando a codificação mais específica para suas classes derivadas.
• Para transferir a codificação de suas funções para as classes derivadas as classes
abstratas usam as chamadas funções virtuais puras.
• Uma função virtual pura não possui definição para a classe em que esta é
declarada como virtual. Nesta está apenas sua declaração.
94 / 125
Herança Múltipla Polimorfismo
Sintaxe para FVP
1 class Classe_Abstrata {
2 ...
3 virtual Função_virtual_pura ()= const;
4 };
Onde const é qualquer valor constante atribuído ao corpo da função ao nível da classe
abstrata. Geralmente este valor é zero.
95 / 125
Herança Múltipla Polimorfismo
Exemplo
1 class Impressora{
2 char * nome;
3 public:
4 virtual int ajuste_parametros ()=0;
5 };
96 / 125
Herança Múltipla Polimorfismo
Mais detalhes sobre FVPs
• A função virtual pura ajuste_parametros deveria ser definida em classes derivadas.
Para que uma classe seja abstrata basta ter uma função virtual pura.
• Qualquer tentativa de declaração de um objeto de uma classe abstrata gera erro
de compilação.
• Entretanto, é permitido declarar-se referências e ponteiros para classes abstratas
desde que estes apontem para objetos de classes derivadas na hierarquia e que,
nestas, as funções virtuais puras tenham sido todas definidas.
• As classes abstratas são frequentes em bibliotecas de classes comerciais
disponíveis no mercado.
97 / 125
Herança Múltipla Polimorfismo
Exemplo Completo
No programa a seguir, a função repõe_estoque é uma função virtual pura na classe
produto, tornando esta uma classe abstrata. Esta classe não pode ter nenhum objeto
criado no programa, porém é permitido a criação de ponteiros para a mesma. Foi
dessa forma que os objetos do programa foram criados dinamicamente e associados as
classes derivadas.
98 / 125
Herança Múltipla Polimorfismo
Exemplo Completo _073_pura.cpp
1 #include <iostream >
2 #include <string >
3 #include <ctime > // Para manipulação de datas
4 using namespace std;
5 // Classe base Produto
6 class Produto {
7 protected:
8 string nome;
9 public:
10 Produto(string nomeProduto) : nome(nomeProduto) {}
11 virtual ~Produto () {}
12 virtual int repoe_estoque () = 0;
13 virtual void mostrar () {
14 cout << "nnnProduto: " << nome << endl;
15 }
16 };
99 / 125
Herança Múltipla Polimorfismo
Exemplo Completo _073_pura.cpp
17 // Classe derivada ProdPerecivel
18 class ProdPerecivel : public Produto {
19 time_t validade;
20 public:
21 ProdPerecivel () : Produto("Produto Perecível") {
22 time (& validade); // Data atual como validade
23 validade += 7 * 24 * 60 * 60; // Acrescenta 7 dias
24 }
25 int repoe_estoque () override {
26 time_t agora;
27 time (& agora);
28 return (difftime(validade, agora) < 3 * 24 * 60 * 60); //
Menos de 3 dias para vencer
29 }
100 / 125
Herança Múltipla Polimorfismo
Exemplo Completo _073_pura.cpp
30 void mostrar () override {
31 Produto :: mostrar ();
32 tm* data = localtime (& validade);
33 cout << "Validade: " << (data ->tm_mday) << "/"
34 << (data ->tm_mon + 1) << "/"
35 << (data ->tm_year + 1900) << endl;
36 }
37 };
101 / 125
Herança Múltipla Polimorfismo
Exemplo Completo _073_pura.cpp
38 // Classe derivada ProdNaoPerecivel
39 class ProdNaoPerecivel : public Produto {
40 long estoque, estoque_minimo ;
41 public:
42 ProdNaoPerecivel () : Produto("Produto Não Perecível"),
estoque (50), estoque_minimo (20) {}
43 int repoe_estoque () override {
44 return estoque < estoque_minimo ;
45 }
46 void mostrar () override {
47 Produto :: mostrar ();
48 cout << "Estoque: " << estoque << ", Estoque Mínimo: " <<
estoque_minimo << endl;
49 }
50 };
102 / 125
Herança Múltipla Polimorfismo
Exemplo Completo _073_pura.cpp
51 int main () {
52 Produto* itens [2];
53 itens [0] = new ProdPerecivel ();
54 itens [1] = new ProdNaoPerecivel ();
55 for (int i = 0; i < 2; i++) {
56 itens[i]->mostrar ();
57 if (itens[i]->repoe_estoque ())
58 cout << "nPrecisa de reposição." << endl;
59 else
60 cout << "nNão precisa de reposição." << endl;
61 delete itens[i];
62 }
63 return 0;
64 }
103 / 125
Herança Múltipla Polimorfismo
Polimorfismo em JAVA
Polimorfismo em Java apresenta algumas semelhanças com C++. Vejamos o primeiro
exemplo usando alocação dinâmica no programa a seguir:
1 class Transacao {
2 String cliente;
3 Transacao(String nome) {
4 cliente = nome;
5 }
6 void mostrar (){ // implemetação 1
7 System.out.println("Transacao a ser realizada. "+"Nome do
Cliente : "+cliente);
8 }
9 }
104 / 125
Herança Múltipla Polimorfismo
Polimorfismo em JAVA - Cont _074_poli.java
10 class Venda_Vista extends Transacao {
11 protected double valor;
12 Venda_Vista (String nome, double preco){
13 super(nome);
14 valor = preco;
15 }
16 void mostrar (){ // implementação 2
17 super.mostrar ();
18 System.out.println("Vanda a vista a ser realizada. "+
19 "Valor da Compra :"
20 +valor);
21 }
22 }
105 / 125
Herança Múltipla Polimorfismo
Polimorfismo em JAVA - Cont _074_poli.java
23 class Venda_Prazo extends Venda_Vista {
24 float juros;
25 Venda_Prazo (String nome, double preco, float taxa){
26 super(nome, preco);
27 juros = taxa;
28 }
29 void mostrar () { // implementação 3
30 super.mostrar ();
31 System.out.println("Venda a prazo a ser realizada. "+"Taxa
Praticada : "+juros+" Total= "+valor *(100+ juros)/100);
32 }
33 }
34 public class _074_poli {
35 public static void main (String [] args) {
36 String nome = "Jose Philomeno";
106 / 125
Herança Múltipla Polimorfismo
Polimorfismo em JAVA - Cont _074_poli.java
37 String nome = "Jose Philomeno";
38 double preco = 10000.;
39 float taxa= 10.f;
40 Transacao [] vendas = new Transacao [3]; // Inicializa a
matriz;
41 vendas [0] = new Transacao(nome);
42 vendas [1] = new Venda_Vista(nome,preco);
43 vendas [2] = new Venda_Prazo(nome,preco,taxa);
44 // Chamada polimorfica
45 for (int i = 0; i < 3; i++) vendas[i].mostrar ();
46 }
47 }
107 / 125
Herança Múltipla Polimorfismo
Funções Virtuais Puras em JAVA / Métodos Abstratos
• Java não possui funções virtuais puras explicitamente, mas possui métodos
abstratos.
• Um método abstrato é funcionalmente equivalente a uma função virtual pura:
• Ele é declarado em uma classe abstrata.
• Deve ser implementado em qualquer classe concreta que herde da classe
abstrata.
108 / 125
Herança Múltipla Polimorfismo
Exemplo de Métodos Abstratos em Java
1 abstract class Animal {
2 abstract void makeSound (); // Método abstrato (sem corpo)
3 }
4
5 class Dog extends Animal {
6 @Override
7 void makeSound () {
8 System.out.println("Woof!");
9 }
10 }
109 / 125
Herança Múltipla Polimorfismo
Classes Abstratas em Java
• Uma classe abstrata em Java é uma classe que não pode ser instanciada
diretamente e pode conter:
• Métodos abstratos (sem implementação).
• Métodos concretos (com implementação).
• Campos (variáveis de instância).
• Classes abstratas são usadas para fornecer uma base comum para classes
relacionadas.
110 / 125
Herança Múltipla Polimorfismo
Exemplo de Classes Abstratas em Java
1 abstract class Shape {
2 abstract double area (); // Método abstrato
3 void description () { // Método concreto
4 System.out.println("This is a shape.");
5 }
6 }
7 class Circle extends Shape {
8 private double radius;
9 Circle(double radius) {
10 this.radius = radius;
11 }
12 @Override
13 double area () {
14 return Math.PI * radius * radius;
15 }
16 }
111 / 125
Herança Múltipla Polimorfismo
Destrutores em Java
• Java não possui destrutores, pois o gerenciamento de memória é feito
automaticamente pelo Garbage Collector (GC).
• O método finalize(), que era usado para liberar recursos, foi descontinuado a
partir do Java 9 e removido no Java 18, pois o GC é considerado suficiente na
maioria dos casos.
• Para liberar recursos não gerenciados (como arquivos ou conexões de banco de
dados), Java recomenda o uso do try-with-resources com a interface
AutoCloseable
112 / 125
Herança Múltipla Polimorfismo
AutoCloseable
Exemplo de uso da interface AutoCloseable.
1 class Resource implements AutoCloseable {
2 public void use() {
3 System.out.println("Using resource");
4 }
5 @Override
6 public void close () {
7 System.out.println("Resource closed");
8 }
9 }
10 public class Main {
11 public static void main(String [] args) {
12 try (Resource res = new Resource ()) {
13 res.use();
14 } // O método close () é chamado automaticamente aqui
15 }
16 } 113 / 125
Herança Múltipla Polimorfismo
Polimorfismo em Python
Nas linguagens modernas, polimorfismo se refere ao fato de que o compilador seja
capaz de identificar em tempo de execução (durante a execução do programa) qual a
subclasse, dentro de uma hierarquia de classes, que responderá a uma determinada
chamada de método.
1 class Video:
2 def __init__(self, arquivo):
3 if not arquivo.endswith(self.ext):
4 raise Exception("Formato de vídeo Inválido")
5 self.arquivo = arquivo
114 / 125
Herança Múltipla Polimorfismo
Polimorfismo em Python
1 from arquivoVideo import *
2 class VideoMP4(Video):
3 ext = "mp4"
4 def reproduzir(self):
5 print("Reproduzindo {} como mp4".for mat(self.arquivo))
6 class VideoAVI(Video):
7 ext = "avi"
8 def reproduzir(self):
9 print("Reproduzindo {} como avi".for mat(self.arquivo))
10 class VideoMOV(Video):
11 ext = "mov"
12 def reproduzir(self):
13 print("Reproduzindo {} como mov".for mat(self.arquivo))
115 / 125
Herança Múltipla Polimorfismo
Polimorfismo em Python
1 from videoMP4 import *
2
3 mp4 = VideoMP4("filme.mp4")
4 mp4.reproduzir ()
5 avi = VideoAVI("filme.avi")
6 avi.reproduzir ()
7 mov = VideoMOV("filme.mov")
8 mov.reproduzir ()
9 #outro = VideoMP4 (" filme.avi")
Saída Normal
Reproduzindo filme.mp4 como mp4
Reproduzindo filme.avi como avi
Reproduzindo filme.mov como mov
116 / 125
Herança Múltipla Polimorfismo
Polimorfismo em Python
1 from videoMP4 import *
2
3 outro = VideoMP4("filme.avi")
Saída Normal
Traceback (most recent call last): File "/home/ramos/googleDrive/inProgress/tu-
torialPOO/latex/fontes/reproduz2.py", line 3, in <module>
outro = VideoMP4("filme.avi")
raise Exception("Formato de vídeo Inválido")
Exception: Formato de vídeo Inválido
117 / 125
Herança Múltipla Polimorfismo
Polimorfismo em Python
Duck Typing (Tipos dinâmicos) do Python provêm uma forma muito mais poderosa de
polimorfismo que o apresentado pelas linguagens que usam tipos estáticos. Ou seja, no
Python o polimorfismo ocorre de forma natural.
118 / 125
Herança Múltipla Polimorfismo
Funções Virtuais em Python
• Python não possui funções virtuais no sentido tradicional de linguagens como
C++. No entanto, devido ao suporte a herança e ao polimorfismo, o
comportamento é semelhante.
• Em Python, todos os métodos em uma classe base são virtualmente sobrescritos
nas subclasses (por padrão). Isso significa que o método da subclasse será
chamado, mesmo quando acessado por meio de uma referência à classe base.
119 / 125
Herança Múltipla Polimorfismo
Usando métodos virtuais em python
1 class Animal:
2 def make_sound(self):
3 print("qualquer som genérico")
4 class Dog(Animal):
5 def make_sound(self):
6 print("Woof!")
7 animal = Animal ()
8 dog = Dog()
9 animal.make_sound () # Saída: Some generic sound
10 dog.make_sound () # Saída: Woof!
11 # Polimorfismo em ação
12 animal = Dog() # Referência da classe base aponta para uma
sub classe
13 animal.make_sound () # Saída: Woof!
120 / 125
Herança Múltipla Polimorfismo
Classes Abstratas em Python
• Em Python, são implementadas com o módulo abc.
• A verificação da obrigatoriedade de implementação de métodos abstratos ocorre
em tempo de execução.
121 / 125
Herança Múltipla Polimorfismo
Classes Abstratas em Python _079_abstrata.py
1 from abc import ABC, abstractmethod
2 # Definindo a classe abstrata
3 class Veiculo(ABC):
4 @abstractmethod
5 def ligar(self):
6 """Método abstrato que deve ser implementado pelas
sub class es"""
7 pass
8 @abstractmethod
9 def desligar(self):
10 """Método abstrato que deve ser implementado pelas
sub class es"""
11 pass
12 def descricao(self):
13 """Método concreto (opcional)"""
14 print("Isto e um veículo.")
122 / 125
Herança Múltipla Polimorfismo
Classes Abstratas em Python _079_abstrata.py
15 # Sub classe concreta
16 class Carro(Veiculo):
17 def ligar(self):
18 print("Motor do Carro ligado.")
19 def desligar(self):
20 print("Motor do Carro desligado.")
21 # Outra sub classe concreta
22 class Moto(Veiculo):
23 def ligar(self):
24 print("Motor da moto ligado.")
25 def desligar(self):
26 print("Motor da moto desligado.")
123 / 125
Herança Múltipla Polimorfismo
Classes Abstratas em Python _079_abstrata.py
27 print("Motor da moto desligado.")
28 # Tentativa de instanciar a classe abstrata
29 try:
30 Veiculo = Veiculo () # Isso gera um erro
31 except TypeError as e:
32 print(f"Erro gerado: {e}")
33
34 # Usando as sub class es concretas
35 Carro = Carro ()
36 Carro.ligar () # Saída: Motor do Carroro ligado.
37 Carro.desligar () # Saída: Motor do Carroro desligado.
38 Carro.descricao () # Saída: Isto é um veículo.
39
40 Moto = Moto ()
41 Moto.ligar () # Saída: Motor da moto ligado.
42 Moto.desligar () # Saída: Motor da moto desligado.
43 Moto.descricao () # Saída: Isto é um veículo. 124 / 125
Herança Múltipla Polimorfismo
CONTINUA
125 / 125

programacao orientada a objetos curso_comparativo_poo_4_5.pdf

  • 1.
    Herança Múltipla Polimorfismo ProgramaçãoOrientada a Objetos Tutorial Básico Multi Linguagens Ronaldo F. Ramos IFCE 1 de dezembro de 2024 1 / 125
  • 2.
    Herança Múltipla Polimorfismo Conteúdo 1Herança Múltipla 2 Polimorfismo 2 / 125
  • 3.
    Herança Múltipla Polimorfismo HerançaMúltipla A herança múltipla entre classes ocorre sempre que uma classe derivada possui duas ou mais classes bases imediatas, ou seja, é “filha” de mais do que uma classe. Tipicamente, a herança múltipla surge quando características de classes são combinadas para formar uma única classe. 3 / 125
  • 4.
    Herança Múltipla Polimorfismo HerançaMúltipla em C++ Sintaxe: 1 class Nome_ classe : [modificador] classe base1 2 [modificador] class ebase2{ 3 // declaracao dos membros 4 }; O modificador default é private. Ex. 1 class D : public A, public C{ 2 // declaração dos membros de D 3 }; 4 / 125
  • 5.
    Herança Múltipla Polimorfismo Construtorese Destrutores com herança múltipla Analogamente à herança simples, a classe derivada, pode acessar os construtores de suas classes base. Sintaxe: 1 Classe_derivada (atrib.ClassDerivada, atribClasseBase1 ,..., baseN) : ClasseBase1( atr.class base1), ..., ClasseBasen( atribClasseBaseN ){ 2 // função construtora da classe derivada 3 }; Atributos significam os dados da classe. No caso da classe derivada, seus atributos são aqueles declarados unicamente em seu escopo ( excluem-se os herdados das classes bases) 5 / 125
  • 6.
    Herança Múltipla Polimorfismo Exemploem C++ _055_heramult.cpp 1 #include <ncurses.h> 2 #include <cstring > 3 #include <cctype > 4 #include <iostream > 5 /* atenção este programa usa a biblioteca ncurses 6 para instalar usar: sudo apt -get install libncurses5 -dev libncursesw5 -dev 7 para compilar: g++ -o heramult _055_heramult.cpp -lncurses */ 8 const int HORIZ_MAX = 80; 9 const int VERT_MAX = 25; 10 class Horizontal { 11 char tipoh; 12 public: 13 Horizontal(char tipo) : tipoh(tipo) {} 14 int posicao_horizontal (const char* texto); 15 }; 6 / 125
  • 7.
    Herança Múltipla Polimorfismo Exemploem C++ _055_hermult.cpp 16 class Vertical { 17 char tipov; 18 public: 19 Vertical(char tipo) : tipov(tipo) {} 20 int posicao_vertical (); 21 }; 22 class Mensagem : public Horizontal, public Vertical { 23 char msg [50]; 24 public: 25 Mensagem(const char* texto, char ver, char hor) 26 : Vertical(ver), Horizontal(hor) { 27 strcpy(msg, texto); 28 } 7 / 125
  • 8.
    Herança Múltipla Polimorfismo Exemploem C++ _055_hermult.cpp 29 void mostrar () { 30 int col = posicao_horizontal (msg); 31 int lin = posicao_vertical (); 32 move(lin, col); // Posiciona o cursor no terminal 33 printw("%s", msg); // Exibe a mensagem 34 refresh (); 35 } 36 }; 37 // Implementação das funções de alinhamento horizontal 38 int Horizontal :: posicao_horizontal (const char* texto) { 39 unsigned tam = strlen(texto); 40 switch (tipoh) { 41 case ’C’: return (( HORIZ_MAX - tam) / 2); 42 case ’D’: return (HORIZ_MAX - tam); 43 def ault: return 1; 44 } 45 } 8 / 125
  • 9.
    Herança Múltipla Polimorfismo Exemploem C++ _055_hermult.cpp 46 // Implementação das funções de alinhamento vertical 47 int Vertical :: posicao_vertical () { 48 switch (tipov) { 49 case ’M’: return (VERT_MAX / 2); 50 case ’R’: return VERT_MAX - 1; // Ajustado para índice 0-base 51 def ault: return 1; 52 } 53 } 9 / 125
  • 10.
    Herança Múltipla Polimorfismo Exemploem C++ _055_hermult.cpp 54 int main () { 55 char texto [50], hor, ver; 56 // Inicializa ncurses 57 initscr (); 58 noecho (); 59 cbreak (); 60 do { 61 clear (); 62 mvprintw (2, 10, "Entre com o Texto: "); 63 echo (); 64 getnstr(texto, 50); // Entrada de texto 65 noecho (); 10 / 125
  • 11.
    Herança Múltipla Polimorfismo Exemploem C++ _055_hermult.cpp 66 // Alinhamento Horizontal 67 do { 68 clear (); 69 mvprintw (2, 10, "Alinhamento Horizontal:"); 70 mvprintw (4, 10, "(E)squerdat(C)entradot(D)ireita:"); 71 hor = toupper(getch ()); 72 } while (hor != ’E’ && hor != ’C’ && hor != ’D’); 73 // Alinhamento Vertical 74 do { 75 clear (); 76 mvprintw (5, 10, "Alinhamento Vertical:"); 77 mvprintw (7, 10, "(T)opott(M)eiott(R)oda -pe:"); 78 ver = toupper(getch ()); 79 } while (ver != ’T’ && ver != ’M’ && ver != ’R’); 11 / 125
  • 12.
    Herança Múltipla Polimorfismo Exemploem C++ _055_hermult.cpp 80 // Exibir mensagem 81 Mensagem tela(texto, ver, hor); 82 clear (); 83 tela.mostrar (); 84 getch (); 85 // Pergunta de continuação 86 clear (); 87 mvprintw (10, 10, "Deseja continuar? (S/N):"); 88 } while (toupper(getch ()) == ’S’); 89 // Finaliza ncurses 90 endwin (); 91 return 0; 92 } 12 / 125
  • 13.
    Herança Múltipla Polimorfismo Ambiguidades Aambiguidade corre quando as classes base possuem membros homônimos não existentes na classe derivada. Quando um objeto da classe derivada tentar referenciar este membro homônimo das classes base, o compilador não reconhecerá a qual classe está se referindo. 13 / 125
  • 14.
    Herança Múltipla Polimorfismo Exemplode Ambiguidades em C++ 1 class Surf{ 2 float notas [10]; // ordem decrescente de notas 3 public: 4 void ordena (); 5 }; 6 class Vela{ 7 float tempos [10]; 8 public: 9 void ordena (); // ordem crescente de tempos 10 } 11 class WIndSurf : public Surf, public Vela{ 12 char competicao; 13 }; 14 / 125
  • 15.
    Herança Múltipla Polimorfismo Problema1 Caso um objeto da classe WindSurf fosse criado e tentasse utilizar a função ordena() de uma classe base haveria uma ambiguidade detectada pelo compilador. 1 void main (){ 2 WindSurf corrida; 3 corrida.ordena ();// erro de ambiguidade 4 } 15 / 125
  • 16.
    Herança Múltipla Polimorfismo Solução1 1 class WindSurf :public Surf, public Vela{ 2 char competicao; 3 public: 4 void ordena (){ 5 if(competicao ==’E’) 6 Surf :: Ordena (); 7 else 8 Vela :: ordena (); 9 } 10 } 16 / 125
  • 17.
    Herança Múltipla Polimorfismo Ambiguidades- problema 2 (Problema do Diamante) Um segundo tipo de ambiguidades que pode ocorrer, refere-se a uma particularidade da hierarquia das classes em herança múltipla. Suponha um programa onde simplesmente imprime-se um valor de um atributo da classe Classe A (o string Nome), uma vez através da classe B1 e outra através da classe B2, cujas inicializações seguem valores default diferentes. class ClasseB1 : public ClasseA...; class ClasseB2: public ClasseA...; class ClasseC : public ClasseB1, public ClasseB2 .. ; 17 / 125
  • 18.
    Herança Múltipla Polimorfismo Exemplode Ambiguidade na Herança Múltipla _056_diamante.cpp 1 // VIRTDUP.CPP - Duplicidade em super classe na Herança Multipla 2 #include <iostream > 3 #include <string > // Para usar string 4 using namespace std; 5 class ClasseA { 6 protected: 7 string nome; 8 public: 9 void mostrar () const { 10 cout << "nNome na Classet t: " << nome; 11 } 12 }; 18 / 125
  • 19.
    Herança Múltipla Polimorfismo Exemplode Ambiguidade na Herança Múltipla _056_diamante.cpp 13 class ClasseB1 : public ClasseA { 14 public: 15 ClasseB1(const string& n = "ClasseB1") { 16 nome = n; 17 } 18 void mostrar () const { 19 ClasseA :: mostrar (); 20 } 21 }; 19 / 125
  • 20.
    Herança Múltipla Polimorfismo Exemplode Ambiguidade na Herança Múltipla _056_diamante.cpp 22 class ClasseB2 : public ClasseA { 23 public: 24 ClasseB2(const string& n = "ClasseB2") { 25 nome = n; 26 } 27 void mostrar () const { 28 ClasseA :: mostrar (); 29 } 30 }; 20 / 125
  • 21.
    Herança Múltipla Polimorfismo Exemplode Ambiguidade na Herança Múltipla _056_diamante.cpp 31 class ClasseC : public ClasseB1, public ClasseB2 { 32 public: 33 void mostrar () const { 34 ClasseB1 :: mostrar (); 35 ClasseB2 :: mostrar (); 36 } 37 }; 38 int main () { 39 ClasseC objetoClasseC; 40 objetoClasseC.mostrar (); 41 cout << "n"; 21 / 125
  • 22.
    Herança Múltipla Polimorfismo Exemplode Ambiguidade na Herança Múltipla _056_diamante.cpp O membro nome possui dois valores simultâneos, "ClasseB1"e "Classe B2". Na realidade há duas instâncias de superclasse: uma é alcançada pelo caminho ClasseC-ClasseB1-ClasseA e a outra pelo caminho ClasseC-ClasseB2-ClasseA. A solução portanto seria especificar o nome da classe mãe para chamar a função específica, porem erros de acesso a variáveis também podem ocorrer: 1 class ClasseC : public ClasseB1,public ClasseB2{ 2 public: 3 void mostrar (){ 4 strcpy(nome,"ObjetoClasseC"); // erro ambiguidade. 5 ClasseB1 :: mostrar (); 6 ClasseB2 :: mostrar (); 7 } 8 } 22 / 125
  • 23.
    Herança Múltipla Polimorfismo Problemados Construtores 1 class A { 2 public: 3 A() { cout << "Construtor de An"; } 4 }; 5 class B1 : public A { 6 public: 7 B1() { cout << "Construtor de B1n"; } 8 }; 9 class B2 : public A { 10 public: 11 B2() { cout << "Construtor de B2n"; } 12 }; 13 class C : public B1, public B2 { 14 public: 15 C() { cout << "Construtor de Cn"; } 16 }; 23 / 125
  • 24.
    Herança Múltipla Polimorfismo Problemados Construtores 1 int main () { 2 C obj; // qual construtor será executado ?? 3 return 0; 4 } • Ao criar um objeto da classe C, qual construtor de A será chamado? • Como B1 e B2 herdam de A, há duas cópias independentes da classe base A. • O compilador não saberá qual caminho seguir, causando um erro. 24 / 125
  • 25.
    Herança Múltipla Polimorfismo Problemados Construtores 1 int main () { 2 C obj; // qual construtor será executado ?? 3 return 0; 4 } • Ao criar um objeto da classe C, qual construtor de A será chamado? • Como B1 e B2 herdam de A, há duas cópias independentes da classe base A. • O compilador não saberá qual caminho seguir, causando um erro. 24 / 125
  • 26.
    Herança Múltipla Polimorfismo SoluçãoUsando Classes Bases Virtuais • Use a palavra-chave virtual para compartilhar a classe base entre as classes derivadas. • A herança virtual garante que apenas uma instância da classe base (A) seja compartilhada entre as classes derivadas (B1 e B2). • Resolve o problema de ambiguidade. 25 / 125
  • 27.
    Herança Múltipla Polimorfismo Corrigindoo código 1 class A { 2 public: 3 A() { cout << "Construtor de An"; } 4 }; 5 class B1 : virtual public A { 6 public: 7 B1() { cout << "Construtor de B1n"; } 8 }; 9 class B2 : virtual public A { 10 public: 11 B2() { cout << "Construtor de B2n"; } 12 }; 13 class C : public B1, public B2 { 14 public: 15 C() { cout << "Construtor de Cn"; } 16 }; 26 / 125
  • 28.
    Herança Múltipla Polimorfismo ClassesBases Virtuais No estudo de membros estáticos em classes, viu-se que todos os objetos da classe compartilham o mesmo membro quando este é estático. Em uma analogia, a classe base virtual provoca o mesmo efeito para as instâncias superiores na hierarquia da herança múltipla. 27 / 125
  • 29.
    Herança Múltipla Polimorfismo Sintaxeda Definição de Classes Bases Virtuais 1 class Classe_Derivada : [modificador] virtual ClasseBase{...} 28 / 125
  • 30.
    Herança Múltipla Polimorfismo Soluçãopara o Programa Acima 1 class ClasseB1 : public virtual ClasseA{ 2 public: 3 ClasseB1 (char * n = "ClasseB1"){ strcpy(nome,n);} 4 void mostrar (){ClasseA :: mostrar ();} 5 } 6 class ClasseB2 : public virtual ClasseA{ 7 public: 8 ClasseB2 (char * n = "ClasseB2"){ strcpy(nome,n);} 9 void mostrar (){ClasseA :: mostrar ();} 10 } 29 / 125
  • 31.
    Herança Múltipla Polimorfismo Restrição •Classes bases virtuais não podem ter construtores com parâmetros. 30 / 125
  • 32.
    Herança Múltipla Polimorfismo Exemplode Aplicação Seja um programa cujo objetivo é o de contabilizar as despesas de uma pessoa com seu prédio. Os gastos do prédio referem-se ao condomínio e às despesas gerais do edifício, pagos por moradores e proprietários, respectivamente. Um morador que é dono do seu apartamento terá os dois tipos de gastos. 31 / 125
  • 33.
    Herança Múltipla Polimorfismo Exemplode Aplicação - 2 Assim uma pessoa para a qual se deseja contabilizar os gastos estará em uma destas três categorias: 1 class Pessoa{ char nome [31]; } 2 class Morador : public virtual Pessoa{...} 3 class Proprietario: public virtual Pessoa{..} 4 class Morador_proprietario : public Morador, public Proprietario{..} 32 / 125
  • 34.
    Herança Múltipla Polimorfismo ExemploCompleto Usando Classes Bases Virtuais _057_virtual.cpp 1 // virtclas.cpp - Exemplo com Classes Virtuais em C++ 2 #include <iostream > 3 #include <cstring > 4 using namespace std; 5 class Pessoa { 6 protected: 7 char nome [31]; 8 public: 9 void mostrar () { 10 cout << "nNome do Condômino: " << nome << endl; 11 } 12 }; 33 / 125
  • 35.
    Herança Múltipla Polimorfismo ExemploCompleto Usando Classes Bases Virtuais _057_virtual.cpp 13 class Morador : virtual public Pessoa { 14 protected: 15 float condominio; 16 public: 17 Morador(const char* nome_mor, float cond) { 18 strncpy(nome, nome_mor, sizeof(nome) - 1); 19 nome[sizeof(nome) - 1] = ’0’; // Garante terminação segura 20 condominio = cond; 21 } 22 }; 34 / 125
  • 36.
    Herança Múltipla Polimorfismo ExemploCompleto Usando Classes Bases Virtuais _057_virtual.cpp 23 class Proprietario : virtual public Pessoa { 24 protected: 25 float despesas; 26 public: 27 Proprietario(const char* nome_prop, float gastos) { 28 strncpy(nome, nome_prop, sizeof(nome) - 1); 29 nome[sizeof(nome) - 1] = ’0’; // Garante terminação segura 30 despesas = gastos; 31 } 32 }; 35 / 125
  • 37.
    Herança Múltipla Polimorfismo ExemploCompleto Usando Classes Bases Virtuais _057_virtual.cpp 33 class Morador_proprietario : public Morador, public Proprietario { 34 public: 35 Morador_proprietario (const char* nome_mp, float cond, float gastos) 36 : Morador(nome_mp, cond), Proprietario(nome_mp, gastos) { 37 strncpy(nome, nome_mp, sizeof(nome) - 1); 38 nome[sizeof(nome) - 1] = ’0’; // Garante terminação segura 39 } 40 void mostrar_ () { 41 mostrar (); // chamada ambígua sem a classe virtual porque a classe derivada terá duas cópias das duas 42 // class es bases respectivamente 43 cout << "Condomínio: R$ " << condominio << endl; 44 cout << "Despesas: R$ " << despesas << endl; 45 } 46 }; 36 / 125
  • 38.
    Herança Múltipla Polimorfismo ExemploCompleto Usando Classes Bases Virtuais _057_virtual.cpp 47 int main () { 48 // Exemplo de uso 49 Morador_proprietario mp("João Silva", 800.50, 1200.75); 50 mp.mostrar_ (); 51 return 0; 52 } 37 / 125
  • 39.
    Herança Múltipla Polimorfismo Resultado Casoa classe base pessoa não fosse declarada como virtual nas heranças de Proprietário e Morador, ocorreria um erro de ambiguidade. 1 void Morador_proprietario :: mostrar(void){ 2 mostrar () // ambiguidade de caminhos 3 ... 4 } O erro apontado pelo compilador seria o seguinte: "member is ambiguous:’Pessoa::mostrar’ and ’Pessoa::Mostrar’"O compilador não sabe qual o caminho a tomar até a raiz, se passando pela classe Morador ou pela classe Proprietário. 38 / 125
  • 40.
    Herança Múltipla Polimorfismo HerançaMúltipla em JAVA A linguagem Java não implementa a herança múltipla, mas podemos usar algo parecido usando interfaces. 39 / 125
  • 41.
    Herança Múltipla Polimorfismo Interfacescomo Solução • Interfaces permitem múltiplas heranças sem ambiguidades: • Uma classe pode implementar várias interfaces. • Cada interface define apenas contratos (métodos abstratos) (Sem implementação). • A implementação é responsabilidade da classe que as implementa. 40 / 125
  • 42.
    Herança Múltipla Polimorfismo Exemplode Uso de Interfaces Definindo interfaces: 1 interface Animal { 2 void comer (); 3 } 4 interface Passaro { 5 void voar (); 6 } Implementando interfaces: 1 class Bat implements Animal, Passaro { 2 public void comer () { 3 System.out.println("Comento..."); 4 } 5 public void voar () { 6 System.out.println("Voando..."); 7 } 8 } 41 / 125
  • 43.
    Herança Múltipla Polimorfismo Vantagensdo Uso de Interfaces • Evita ambiguidade da herança múltipla. • Promove maior flexibilidade e modularidade. • Permite a criação de classes altamente coesas e de fácil manutenção. 42 / 125
  • 44.
    Herança Múltipla Polimorfismo Desvantagensdo Uso de Interfaces • Implementações obrigatórias nas classes derivadas • Ausência de Estado Compartilhado • Complexidade Crescente com Interfaces Múltiplas 43 / 125
  • 45.
    Herança Múltipla Polimorfismo ImplementaçãoObrigatória de Métodos/Métodos Default • Interfaces podem incluir métodos default (a partir do Java 8), que oferecem uma implementação padrão. • Nesse caso, a classe que implementa a interface não é obrigada a sobrescrever esses métodos. • No entanto, os métodos abstratos ainda precisam ser implementados. 44 / 125
  • 46.
    Herança Múltipla Polimorfismo Exemplode Métodos Default 1 interface Animal { 2 void comer (); 3 def ault void dormir () { 4 System.out.println("Animal dormindo"); 5 } 6 } 7 class Cachorro implements Animal { 8 @Override 9 public void comer () { 10 System.out.println("Cachorro comendo"); 11 } 12 // dormir () não precisa ser implementado, pois já tem uma implementação padrão. 13 } 45 / 125
  • 47.
    Herança Múltipla Polimorfismo ExemploCliente Funcionário em JAVA _058_interfaces.java 1 // 2 // Programa cliente_funcionario .java - Ilustra a utilização 3 // de interfaces 4 // 5 interface cliente{ 6 float qualquer = 0; 7 float calcula_renda_liquida (float bruta); 8 } 9 class funcionario{ 10 String Nome = "Ze dos Moveis"; 11 String Setor = "Carpintaria"; 12 String Cargo = "Marcineiro"; 13 float SalarioBruto = 120.00f; 14 } 46 / 125
  • 48.
    Herança Múltipla Polimorfismo ExemploCliente Funcionário em JAVA _058_interfaces.java 15 class cliente_funcionario extends funcionario implements cliente{ 16 public float calcula_renda_liquida (float bruta){ 17 return 0.75f*bruta; 18 } 19 void mostra_dados (){ 20 System.out.println("Nome "+Nome); 21 System.out.println("Setor "+Setor); 22 System.out.println("Cargo "+Cargo); 23 System.out.println("Renda liquida"+ calcula_renda_liquida (SalarioBruto)); 24 } 25 26 } 47 / 125
  • 49.
    Herança Múltipla Polimorfismo ExemploCliente Funcionário em JAVA _058_interfaces.java 27 public class _058_interfaces { 28 static public void main(String Args []){ 29 cliente_funcionario cf = new cliente_funcionario (); 30 cf.mostra_dados (); 31 } 32 } 48 / 125
  • 50.
    Herança Múltipla Polimorfismo HerançaMúltipla em Python _059_pessoa.py Observemos classe Pessoa abaixo. 1 class Pessoa: 2 def __init__(self,nome,end,fone): 3 print("Executando Costrutor de Pessoa ") 4 self.nome,self.endereco,self.telefone = nome,end,fone 5 def __str__(self): 6 return "NOME: "+self.nome+" END. "+self.endereco+" FONE: "+self.telefone 49 / 125
  • 51.
    Herança Múltipla Polimorfismo HerançaMúltipla _060_estudante.py E agora a classe Estudante. 1 from pessoa import * 2 class Estudante(Pessoa): 3 listaEstudantes = [] 4 def __init__(self,nome,end,fone,curso,periodo): 5 print("Executando o construtor de Estudante ") 6 Pessoa.__init__(self, nome,end,fone) 7 self.curso = curso 8 self.periodo = periodo 9 Estudante. listaEstudantes .append(self) 10 11 def calculaIra(self): 12 return 0 50 / 125
  • 52.
    Herança Múltipla Polimorfismo HerançaMúltipla _061_professor.py E agora a classe Professor. 1 from pessoa import * 2 class Professor(Pessoa): 3 listaProfessores = [] 4 def __init__(self,nome,end,fone,listaCursos): 5 print("Executando o construtor de Professor ") 6 Pessoa.__init__(self, nome,end,fone) 7 self.listaCursos = listaCursos 8 Professor. listaProfessores .append(self) 9 10 def calculaCargaHoraria (self): 11 return 0 51 / 125
  • 53.
    Herança Múltipla Polimorfismo HerançaMúltipla _062_estagiario.py Agora imagine um aluno que também é professor. Uma espécie de estagiário de ensino. 1 from estudante import * 2 from professor import * 3 class EstagiarioEnsino (Estudante,Professor): 4 def __init__(self,nome,end,fone,curso,periodo,listaCursos, duracaoEstagio 5 print("Iniciando construtor de estagiário ") 6 Estudante.__init__(self, nome, end, fone, curso, periodo) 7 Professor.__init__(self, nome, end, fone, listaCursos) 8 self.duracaoEstagio = duracaoEstagio 52 / 125
  • 54.
    Herança Múltipla Polimorfismo HerançaMúltipla _063_usaEstagiario.py Agora vamos usar tudo. 1 from estagiario import * 2 def main (): 3 print("Atenção para a ordem de chamada dos construtores ") 4 st = EstagiarioEnsino ("Pedro","Rua das Acacias 43", "98213344","Mecânica",6,["logica","Programação"],24) 5 print("Estagiário criado") 6 7 if __name__ =="__main__": 8 main () 53 / 125
  • 55.
    Herança Múltipla Polimorfismo HerançaMúltipla Saída: 54 / 125
  • 56.
    Herança Múltipla Polimorfismo RevisandoO Problema do Diamante 55 / 125
  • 57.
    Herança Múltipla Polimorfismo Vejamosalgumas modificações no código anterior.Classe Estudante _064_estudanteModificado.py 1 from pessoa import * 2 class Estudante(Pessoa): 3 listaEstudantes = [] 4 def __init__(self,nome,end,fone,curso,periodo): 5 print("Executando o construtor de Estudante ") 6 super ().__init__(self,nome,end,fone) 7 self.curso = curso 8 self.periodo = periodo 9 10 def calculaIra(self): 11 return 0 56 / 125
  • 58.
    Herança Múltipla Polimorfismo ClasseProfessor. _065_professorModificado.py 1 from pessoa import * 2 class Professor(Pessoa): 3 listaProfessores = [] 4 def __init__(self,nome,end,fone,listaCursos): 5 print("Executando o construtor de Professor ") 6 super ().__init__(nome,end,fone) 7 self.listaCursos = listaCursos 8 9 def calculaCargaHoraria (self): 10 return 0 57 / 125
  • 59.
    Herança Múltipla Polimorfismo ClasseEstagiário. _066_estagiarioModificado.py 1 from estudanteModificado import * 2 from professorModificado import * 3 class EstagiarioEnsino (Estudante,Professor): 4 def __init__(self,nome,end,fone,curso,periodo,listaCursos, duracaoEstagio 5 print("Iniciando construtor de estagiário ") 6 super ().__init__(nome, end, fone, curso, periodo) 7 self.duracaoEstagio = duracaoEstagio 58 / 125
  • 60.
    Herança Múltipla Polimorfismo Finalmenteusando tudo. _067_herancaMultiplaSuper.py 1 from pessoa import * 2 from estudanteModificado import * 3 from professorModificado import * 4 from estagiarioModificado import * 5 6 def main (): 7 print("Atenção para a ordem de chamada dos construtores ") 8 st = EstagiarioEnsino ("Pedro","Rua das Acacias 43", "98213344","Mecânica",6,["logica","Programação"],24) 9 print("Estagiário criado") 10 11 if __name__ =="__main__": 12 main () 59 / 125
  • 61.
    Herança Múltipla Polimorfismo Saída... Isso ocorre devido ao algoritmo e MRO (method resolution order). Ver documentação. 60 / 125
  • 62.
    Herança Múltipla Polimorfismo MethodResolution Order O Method Resolution Order (MRO) em Python determina a ordem na qual as classes são pesquisadas para encontrar um método ou atributo quando é feita uma chamada. Ele é crucial para a herança múltipla, pois define a sequência de classes que serão consultadas. Essa ordem é baseada no algoritmo C3 Linearization, que garante uma hierarquia consistente e previsível. 61 / 125
  • 63.
    Herança Múltipla Polimorfismo Funcionamentodo MRO Busca em Profundidade Linearizada (C3 Linearization): • O MRO combina a ordem linear de herança das classes (em profundidade) com a ordem em que elas aparecem na definição de uma classe. • O algoritmo garante que: • Um método ou atributo em uma classe superior não seja sobrescrito por classes subordinadas de forma inconsistente. 1 • A hierarquia respeite a precedência declarada na herança múltipla. 1 Resolve o problema da ambiguidade 62 / 125
  • 64.
    Herança Múltipla Polimorfismo RegraBásica MRO Python busca métodos/atributos em: • A própria classe. • Suas classes-mãe (da esquerda para a direita na declaração de herança). • Classes ascendentes até o topo da hierarquia, que é sempre object 63 / 125
  • 65.
    Herança Múltipla Polimorfismo Exercício Mudea ordem da herança das classes acima e veja o que acontece com a chamada dos construtores. 64 / 125
  • 66.
    Herança Múltipla Polimorfismo ATENÇÃO.Probleminha com argumentos. Os argumentos mudam ao chamar funções da classe mãe pela classe ou pela função super() Pessoa.__init__(self,nome,end,fone) super().__init__(nome,end,fone) As classes mães podem ter listas de argumentos diferentes. Como quem decide é o compilador, poderemos ter problemas. Classe Estudante: def __init__(self,nome,end,fone,curso,periodo): ˙ .. Classe Professor: def __init__(self,nome,end,fone,listaCursos): 65 / 125
  • 67.
    Herança Múltipla Polimorfismo Solução:Sobrecarga?? Argumentos Flexíveis Python usa argumentos flexíveis de várias formas. • Tipos e Retorno dinâmicos (Duck Typing) def calcula(a,b): .̇. calcula(3,4) • Argumentos default def calcula(a=1,b=3,c="maria"): .̇. calcula(1) calcula(1,2) calcula(1,2,"pedro") .̇ • Listas de argumentos def calcula(*list): 66 / 125
  • 68.
    Herança Múltipla Polimorfismo Listasde Argumentos _068_lstaArgumentosSimples.py Observe a definição da função calcula(*lista). O operador * em lista implica que o compilador aceitará qualquer lista de argumentos e colocará em uma lista de strings de nome lista. 1 def imprimeArgs (* args): 2 print("nLista de argumentos:",end="") 3 for a in args: print(a,end=",") 4 def main (): 5 imprimeArgs () 6 imprimeArgs("Uma String") 7 imprimeArgs (23) 8 imprimeArgs("Uma string",2,"Segunda String",[1,2,3,4]," e muito mais") 9 if __name__ =="__main__": 10 main () 67 / 125
  • 69.
    Herança Múltipla Polimorfismo Listasde Argumentos - Saída Observe a saída do programa anterior. Lista de argumentos: Lista de argumentos:Uma String, Lista de argumentos:23, Lista de argumentos:Uma string,2,Segunda String,[1, 2, 3, 4], e muito mais, 68 / 125
  • 70.
    Herança Múltipla Polimorfismo Listasde Argumentos _069_listaArgumentosDicionario.py O duplo ** nos remete a criação de uma estrutura de dados chamada dicionário. Veja. 1 def imprimeArgs (** kwargs): 2 print(kwargs) 3 4 if __name__ =="__main__": 5 imprimeArgs(nome="maria",idade =25,estadoCivil="solteira") Saída. {’nome’: ’maria’, ’idade’: 25, ’estadoCivil’: ’solteira’} 69 / 125
  • 71.
    Herança Múltipla Polimorfismo Listasde Argumentos _070_listaArgumentosDicionarios2.py Trabalhando um pouco os argumentos 1 def imprimeArgs (** kwargs): 2 for rotulo,valor in kwargs.items (): 3 print("%s = %s"%( rotulo, valor)) 4 if __name__ =="__main__": 5 imprimeArgs(nome="maria",idade =25,estadoCivil="solteira") Saída. idade = 25 estadoCivil = solteira nome = maria 70 / 125
  • 72.
    Herança Múltipla Polimorfismo Polimorfismo Conceitoque permite que diferentes classes respondam a chamadas de métodos ou operadores com o mesmo nome, mas com comportamentos específicos para cada classe. O termo vem do grego e significa "muitas formas". Pode ser implementado através de: • Sobrecarga de métodos • Sobrecarga de operadores • Sobrescrita de métodos • implementação de interfaces 71 / 125
  • 73.
    Herança Múltipla Polimorfismo Polimorfismoem C++ Via Função Virtual • O conceito de polimorfismo dá caráter sintético aos programas. Em uma hierarquia, a semelhança de funções pode ocorrer nos diferentes níveis. Por exemplo, pode-se utilizar uma função gravar() para apresentar os membros dos objetos de cada classe na hierarquia. • Com a sobrecarga, poder-se-ia criar uma função gravar() para cada classe e diferenciar-se as mesmas pelo operador de resolução de escopo(::). • O polimorfismo em hierarquias de classes tem uma forma de implementação mais eficiente quando são utilizadas as funções virtuais. 72 / 125
  • 74.
    Herança Múltipla Polimorfismo SintaxeFunções Virtuais 1 class ClasseBase{ 2 virtual Protótipo_função_virtual (); 3 }; 4 class ClasseDerivada :: ClasseBase{ 5 [virtual] Protótipo_função_virtual (); 6 }; 73 / 125
  • 75.
    Herança Múltipla Polimorfismo ExemploPolimorfismo via Função Virtual _071_funcvirt.cpp 1 // FUNCVIRT.CPP - Programa Exemplificando o Uso de Funções Virtuais 2 #include <iostream > 3 #include <string > 4 #include <limits > 5 using namespace std; 6 class Transacao { 7 protected: 8 string cliente; 9 public: 10 Transacao(const string& nome) : cliente(nome) {} 11 virtual void mostrar () { 12 cout << "Nome do Cliente : " << cliente << ’n’; 13 } 14 virtual ~Transacao () {} // Destrutor virtual para garantir limpeza correta 15 }; 74 / 125
  • 76.
    Herança Múltipla Polimorfismo ExemploPolimorfismo via Função Virtual _071_funcvirt.cpp 16 class Venda_Vista : public Transacao { 17 protected: 18 double valor; 19 public: 20 Venda_Vista(const string& nome, double preco) 21 : Transacao(nome), valor(preco) {} 22 void mostrar () override { 23 Transacao :: mostrar (); 24 cout << "Valor da Compra : " << valor << ’n’; 25 } 26 }; 75 / 125
  • 77.
    Herança Múltipla Polimorfismo ExemploPolimorfismo via Função Virtual _071_funcvirt.cpp 27 }; 28 class Venda_Prazo : public Venda_Vista { 29 float juros; 30 public: 31 Venda_Prazo(const string& nome, double preco, float taxa) 32 : Venda_Vista(nome, preco), juros(taxa) {} 33 void mostrar () override { 34 Transacao :: mostrar (); 35 cout << "Taxa Praticada : " << juros << "%n"; 36 cout << "Valor da Compra : " << valor * (100 + juros) / 100 << ’n’; 37 } 38 }; 76 / 125
  • 78.
    Herança Múltipla Polimorfismo ExemploPolimorfismo via Função Virtual _071_funcvirt.cpp 39 int main () { 40 string nome; 41 double preco; 42 float taxa; 43 cout << "Entre com o Nome: "; 44 getline(cin, nome); 45 cout << "Entre com o Valor a Vista: "; 46 cin >> preco; 47 cout << "Entre com a Taxa de Juros (%): "; 48 cin >> taxa; 49 // Usando ponteiros brutos 77 / 125
  • 79.
    Herança Múltipla Polimorfismo ExemploPolimorfismo via Função Virtual _071_funcvirt.cpp 50 Transacao* vendas [3]; 51 vendas [0] = new Transacao(nome); 52 vendas [1] = new Venda_Vista(nome, preco); // chamada polimorfica 53 vendas [2] = new Venda_Prazo(nome, preco, taxa); // idem 54 cout << "nn"; 55 for (int i = 0; i < 3; i++) { 56 vendas[i]->mostrar (); 57 cout << ’n’; 58 } 78 / 125
  • 80.
    Herança Múltipla Polimorfismo ExemploPolimorfismo via Função Virtual _071_funcvirt.cpp 59 // Liberando memória manualmente 60 for (int i = 0; i < 3; i++) { 61 delete vendas[i]; 62 } 63 // Espera o usuário antes de encerrar o programa 64 cout << "Pressione Enter para sair..."; 65 // descarta caracteres do buffer de entrada 66 // 67 cin.ignore (); 68 cin.get(); 69 return 0; 70 } 79 / 125
  • 81.
    Herança Múltipla Polimorfismo Porqueusar Função Virtual • Sem a palavra-chave virtual, o método chamado seria determinado com base no tipo do ponteiro ou referência, não no tipo real do objeto. Isso é chamado de ligação estática (ou early binding), o que não é desejado em muitos casos de herança. • Com virtual, o método chamado é determinado pelo tipo real do objeto apontado pelo ponteiro ou referência (ligação dinâmica ou late binding). Isso permite que o comportamento correto seja executado para objetos das classes derivadas. 80 / 125
  • 82.
    Herança Múltipla Polimorfismo Exercício Éconveniente compararmos o resultado do programa com a simples remoção da palavra virtual da declaração da função mostrar() da classe base Transação. Neste caso o resultado do programa seria: Nome do cliente : nome Nome do cliente : nome Nome do cliente : nome 81 / 125
  • 83.
    Herança Múltipla Polimorfismo Explicação Arazão está no fato de quando mostrar deixa de ser virtual, o compilador não associará sua chamada ao tipo de objeto que a faz. Com a função virtual o compilador decide em tempo de execução , qual o tipo de objeto que está chamando a função mostrar().Isto ocorre no momento das atribuições: vendas[0] = new Transacao(nome); vendas[1] = new Venda_Vista(nome,preco); vendas[2] = new Venda_Prazo(nome,preco,taxa); Uma chamada a vendas[2]->mostrar() chamará Vendas_Prazo::mostrar() e não Transacao::mostrar(). 82 / 125
  • 84.
    Herança Múltipla Polimorfismo AlternativaUsando Referências Uma alternativa a esta implementação é a utilização de referências à classe base transação. Para tal o programa receberia as seguintes modificações na função main(): 1 void main (){ 2 ... 3 Trasacao ObjTransacao(nome); // objeto da base 4 Venda_Vista objVenda_Vista(nome, preco);// derivada 5 Venda_Prazo objVenda_Prazo(nome,preco,taxa); // idem 6 Transacao & vendas1 = objTransacao; // refere. 7 Transacao & vendas2 = objVenda_vista; 8 Transacao & vendas3 = objVenda_Prazo; 9 ... 10 } Pense em algo mais elegante. 83 / 125
  • 85.
    Herança Múltipla Polimorfismo Restrições •A função deve ser declarada como virtual na classe base caso contrário o compilador entenderá que a classe na qual a função aparece deverá ter herdeiras com esta função. • A função virtual deve estar definida na classe base, mesmo sem código algum. • Os protótipos de funções virtuais nas classes derivadas devem ser idênticos ao protótipo da classe base. Caso contrário ocorrerá sobrecarga de funções. • Construtores não podem ser funções virtuais.Pelo fato de que cosntrutores não são herdados. Já destrutores não só é possível como útil. • Caso o modificador de herança não seja public não se poderá criar uma referência para acesso à classe privada via base. Erro de conversão. 84 / 125
  • 86.
    Herança Múltipla Polimorfismo Exemplosde Erros 1 class ClasseBase { 2 public : 3 virtual void funcao_virtual () { 4 cout << "Esta e’ a ClasseBase !!n"; 5 } 6 }; 7 // B) ERRO - NAO DEFINIR A FUNCAO VIRTUAL PARA A CLASSE BASE 8 // void funcao_virtual ();}; // so’ declarada 9 // C) WARNING - USAR PROTOTIPOS DIFERENTES P/ A FUNCAO VIRTUAL. 10 // virtual void funcao_virtual (char * msg) { 11 // cout << msg << "n";}}; 12 // Warning :’ClasseDerivada :: prototipo1_funcao_virtual ()’ hides virtual 13 // function ’ClasseBase :: prototipo2_funcao_virtual ()’ 14 // D) ERRO - CONSTRUTOR VIRTUAL 15 // virtual ClasseBase () { 16 // cout << "Construcao da ClasseBase ";}}; 85 / 125
  • 87.
    Herança Múltipla Polimorfismo DestrutoresVirtuais • Destrutores definidos também para as classes derivadas, é aconselhável definí-los como virtual. • Estes não causam problemas quando apenas objetos na hierarquia são definidos. Porém caso algum objeto derivado seja criado através de ponteiro para a classe base , certamente o funcionamento dos destrutores sobrecarregados causará problemas ao programa. 86 / 125
  • 88.
    Herança Múltipla Polimorfismo DestrutoresVirtuais Observando o programa a seguir verifica-se que apenas o destrutor da classe base Pessoa foi chamado na execução do comando delete ptrPessoa. da função main(). Com isso o programa deixou de desalocar a memória dinâmica reservada para informações adicionais( atributo informações da classe referência) e não gravaria as referências dadas pelo usuário. 87 / 125
  • 89.
    Herança Múltipla Polimorfismo DestrutoresVirtuais - Cont - _072_desvirt.cpp 1 #include <iostream > 2 #include <cstring > 3 #include <cctype > 4 using namespace std; 5 char newline, confirma; 6 class Pessoa { 7 protected: 8 char* nome; 9 private: 10 char telefone [13]; 11 public: 12 Pessoa(char*, char *); 13 virtual ~Pessoa (); // Destrutor virtual 14 }; 88 / 125
  • 90.
    Herança Múltipla Polimorfismo DestrutoresVirtuais - Cont _072_desvirt.cpp 15 class Referencias : public Pessoa { 16 char* infor macoes; 17 public: 18 Referencias(char*, char *); 19 ~Referencias (); 20 }; 21 int main () { 22 while (1) { 23 char nom [31], fone [13]; 24 Pessoa* ptrPessoa; 25 cout << "DADOS PESSOAIS : " << endl; 26 cout << "Nome : "; 27 cin.getline(nom, 30); 89 / 125
  • 91.
    Herança Múltipla Polimorfismo DestrutoresVirtuais - Cont _072_desvirt.cpp 28 cout << "Telefone : "; 29 cin.getline(fone, 12); 30 cout << "nDeseja Anotar Referencias sobre a Pessoa (S/N) ?? " << flush; 31 cin.get(confirma); 32 cin.get(newline); 33 if (( toupper(confirma) != ’S’) && (confirma != ’n’)) 34 ptrPessoa = new Pessoa(nom, fone); 35 else 36 ptrPessoa = new Referencias(nom, fone); 37 delete ptrPessoa; 38 cout << "nnDeseja Continuar : (S/N) "; 90 / 125
  • 92.
    Herança Múltipla Polimorfismo DestrutoresVirtuais - Cont _072_desvirt.cpp 39 cin.get(confirma); 40 cin.get(newline); 41 if (toupper(confirma) != ’S’) break; 42 } 43 return 0; 44 } 45 Pessoa :: Pessoa(char* nom, char* fone) { 46 nome = new char[strlen(nom) + 1]; 47 strcpy(nome, nom); 48 strcpy(telefone, fone); 49 } 50 Pessoa ::~ Pessoa () { 51 cout << "nGravando Nome e Telefone de " << nome << " ..." << endl; 52 delete [] nome; 53 // Deve -se implementar a gravação em arquivo 54 } 91 / 125
  • 93.
    Herança Múltipla Polimorfismo DestrutoresVirtuais - Cont _072_desvirt.cpp 55 Referencias :: Referencias(char* nom, char* fone) : Pessoa(nom, fone) { 56 char aux [300]; 57 cout << "nnnREFERENCIAS SOBRE " << nome << " : nn"; 58 cin.getline(aux, 300); 59 infor macoes = new char[strlen(aux) + 1]; 60 strcpy(infor macoes, aux); 61 } 62 Referencias ::~ Referencias () { 63 cout << "Destruindo a classe derivada"<<endl; 64 cout << "nnGravando Infor macoes sobre " << nome << " ..." << endl; 65 delete [] infor macoes; 66 } 92 / 125
  • 94.
    Herança Múltipla Polimorfismo SoluçõesCabíveis • Criação direta do objeto: Referencias objReferencia(nom,fone); • Criação de um ponteiro para a classe derivada Referencias: Referencias * ptrReferencias = new Referencias(nom,fone); • No programa anterior para continuar usando o ponteiro para a classe base na criação de objetos de ambas as classes na hierarquia, o destrutor desta classe deve ser declarado como virtual. : virtual Pessoa() 93 / 125
  • 95.
    Herança Múltipla Polimorfismo ClassesAbstratas e Funções Virtuais Puras • Em C++ as classes que não possuem objetos são denominadas classes abstratas. Nestes tipos de classe não há definição para o código de pelo menos uma de suas funções, ficando a codificação mais específica para suas classes derivadas. • Para transferir a codificação de suas funções para as classes derivadas as classes abstratas usam as chamadas funções virtuais puras. • Uma função virtual pura não possui definição para a classe em que esta é declarada como virtual. Nesta está apenas sua declaração. 94 / 125
  • 96.
    Herança Múltipla Polimorfismo Sintaxepara FVP 1 class Classe_Abstrata { 2 ... 3 virtual Função_virtual_pura ()= const; 4 }; Onde const é qualquer valor constante atribuído ao corpo da função ao nível da classe abstrata. Geralmente este valor é zero. 95 / 125
  • 97.
    Herança Múltipla Polimorfismo Exemplo 1class Impressora{ 2 char * nome; 3 public: 4 virtual int ajuste_parametros ()=0; 5 }; 96 / 125
  • 98.
    Herança Múltipla Polimorfismo Maisdetalhes sobre FVPs • A função virtual pura ajuste_parametros deveria ser definida em classes derivadas. Para que uma classe seja abstrata basta ter uma função virtual pura. • Qualquer tentativa de declaração de um objeto de uma classe abstrata gera erro de compilação. • Entretanto, é permitido declarar-se referências e ponteiros para classes abstratas desde que estes apontem para objetos de classes derivadas na hierarquia e que, nestas, as funções virtuais puras tenham sido todas definidas. • As classes abstratas são frequentes em bibliotecas de classes comerciais disponíveis no mercado. 97 / 125
  • 99.
    Herança Múltipla Polimorfismo ExemploCompleto No programa a seguir, a função repõe_estoque é uma função virtual pura na classe produto, tornando esta uma classe abstrata. Esta classe não pode ter nenhum objeto criado no programa, porém é permitido a criação de ponteiros para a mesma. Foi dessa forma que os objetos do programa foram criados dinamicamente e associados as classes derivadas. 98 / 125
  • 100.
    Herança Múltipla Polimorfismo ExemploCompleto _073_pura.cpp 1 #include <iostream > 2 #include <string > 3 #include <ctime > // Para manipulação de datas 4 using namespace std; 5 // Classe base Produto 6 class Produto { 7 protected: 8 string nome; 9 public: 10 Produto(string nomeProduto) : nome(nomeProduto) {} 11 virtual ~Produto () {} 12 virtual int repoe_estoque () = 0; 13 virtual void mostrar () { 14 cout << "nnnProduto: " << nome << endl; 15 } 16 }; 99 / 125
  • 101.
    Herança Múltipla Polimorfismo ExemploCompleto _073_pura.cpp 17 // Classe derivada ProdPerecivel 18 class ProdPerecivel : public Produto { 19 time_t validade; 20 public: 21 ProdPerecivel () : Produto("Produto Perecível") { 22 time (& validade); // Data atual como validade 23 validade += 7 * 24 * 60 * 60; // Acrescenta 7 dias 24 } 25 int repoe_estoque () override { 26 time_t agora; 27 time (& agora); 28 return (difftime(validade, agora) < 3 * 24 * 60 * 60); // Menos de 3 dias para vencer 29 } 100 / 125
  • 102.
    Herança Múltipla Polimorfismo ExemploCompleto _073_pura.cpp 30 void mostrar () override { 31 Produto :: mostrar (); 32 tm* data = localtime (& validade); 33 cout << "Validade: " << (data ->tm_mday) << "/" 34 << (data ->tm_mon + 1) << "/" 35 << (data ->tm_year + 1900) << endl; 36 } 37 }; 101 / 125
  • 103.
    Herança Múltipla Polimorfismo ExemploCompleto _073_pura.cpp 38 // Classe derivada ProdNaoPerecivel 39 class ProdNaoPerecivel : public Produto { 40 long estoque, estoque_minimo ; 41 public: 42 ProdNaoPerecivel () : Produto("Produto Não Perecível"), estoque (50), estoque_minimo (20) {} 43 int repoe_estoque () override { 44 return estoque < estoque_minimo ; 45 } 46 void mostrar () override { 47 Produto :: mostrar (); 48 cout << "Estoque: " << estoque << ", Estoque Mínimo: " << estoque_minimo << endl; 49 } 50 }; 102 / 125
  • 104.
    Herança Múltipla Polimorfismo ExemploCompleto _073_pura.cpp 51 int main () { 52 Produto* itens [2]; 53 itens [0] = new ProdPerecivel (); 54 itens [1] = new ProdNaoPerecivel (); 55 for (int i = 0; i < 2; i++) { 56 itens[i]->mostrar (); 57 if (itens[i]->repoe_estoque ()) 58 cout << "nPrecisa de reposição." << endl; 59 else 60 cout << "nNão precisa de reposição." << endl; 61 delete itens[i]; 62 } 63 return 0; 64 } 103 / 125
  • 105.
    Herança Múltipla Polimorfismo Polimorfismoem JAVA Polimorfismo em Java apresenta algumas semelhanças com C++. Vejamos o primeiro exemplo usando alocação dinâmica no programa a seguir: 1 class Transacao { 2 String cliente; 3 Transacao(String nome) { 4 cliente = nome; 5 } 6 void mostrar (){ // implemetação 1 7 System.out.println("Transacao a ser realizada. "+"Nome do Cliente : "+cliente); 8 } 9 } 104 / 125
  • 106.
    Herança Múltipla Polimorfismo Polimorfismoem JAVA - Cont _074_poli.java 10 class Venda_Vista extends Transacao { 11 protected double valor; 12 Venda_Vista (String nome, double preco){ 13 super(nome); 14 valor = preco; 15 } 16 void mostrar (){ // implementação 2 17 super.mostrar (); 18 System.out.println("Vanda a vista a ser realizada. "+ 19 "Valor da Compra :" 20 +valor); 21 } 22 } 105 / 125
  • 107.
    Herança Múltipla Polimorfismo Polimorfismoem JAVA - Cont _074_poli.java 23 class Venda_Prazo extends Venda_Vista { 24 float juros; 25 Venda_Prazo (String nome, double preco, float taxa){ 26 super(nome, preco); 27 juros = taxa; 28 } 29 void mostrar () { // implementação 3 30 super.mostrar (); 31 System.out.println("Venda a prazo a ser realizada. "+"Taxa Praticada : "+juros+" Total= "+valor *(100+ juros)/100); 32 } 33 } 34 public class _074_poli { 35 public static void main (String [] args) { 36 String nome = "Jose Philomeno"; 106 / 125
  • 108.
    Herança Múltipla Polimorfismo Polimorfismoem JAVA - Cont _074_poli.java 37 String nome = "Jose Philomeno"; 38 double preco = 10000.; 39 float taxa= 10.f; 40 Transacao [] vendas = new Transacao [3]; // Inicializa a matriz; 41 vendas [0] = new Transacao(nome); 42 vendas [1] = new Venda_Vista(nome,preco); 43 vendas [2] = new Venda_Prazo(nome,preco,taxa); 44 // Chamada polimorfica 45 for (int i = 0; i < 3; i++) vendas[i].mostrar (); 46 } 47 } 107 / 125
  • 109.
    Herança Múltipla Polimorfismo FunçõesVirtuais Puras em JAVA / Métodos Abstratos • Java não possui funções virtuais puras explicitamente, mas possui métodos abstratos. • Um método abstrato é funcionalmente equivalente a uma função virtual pura: • Ele é declarado em uma classe abstrata. • Deve ser implementado em qualquer classe concreta que herde da classe abstrata. 108 / 125
  • 110.
    Herança Múltipla Polimorfismo Exemplode Métodos Abstratos em Java 1 abstract class Animal { 2 abstract void makeSound (); // Método abstrato (sem corpo) 3 } 4 5 class Dog extends Animal { 6 @Override 7 void makeSound () { 8 System.out.println("Woof!"); 9 } 10 } 109 / 125
  • 111.
    Herança Múltipla Polimorfismo ClassesAbstratas em Java • Uma classe abstrata em Java é uma classe que não pode ser instanciada diretamente e pode conter: • Métodos abstratos (sem implementação). • Métodos concretos (com implementação). • Campos (variáveis de instância). • Classes abstratas são usadas para fornecer uma base comum para classes relacionadas. 110 / 125
  • 112.
    Herança Múltipla Polimorfismo Exemplode Classes Abstratas em Java 1 abstract class Shape { 2 abstract double area (); // Método abstrato 3 void description () { // Método concreto 4 System.out.println("This is a shape."); 5 } 6 } 7 class Circle extends Shape { 8 private double radius; 9 Circle(double radius) { 10 this.radius = radius; 11 } 12 @Override 13 double area () { 14 return Math.PI * radius * radius; 15 } 16 } 111 / 125
  • 113.
    Herança Múltipla Polimorfismo Destrutoresem Java • Java não possui destrutores, pois o gerenciamento de memória é feito automaticamente pelo Garbage Collector (GC). • O método finalize(), que era usado para liberar recursos, foi descontinuado a partir do Java 9 e removido no Java 18, pois o GC é considerado suficiente na maioria dos casos. • Para liberar recursos não gerenciados (como arquivos ou conexões de banco de dados), Java recomenda o uso do try-with-resources com a interface AutoCloseable 112 / 125
  • 114.
    Herança Múltipla Polimorfismo AutoCloseable Exemplode uso da interface AutoCloseable. 1 class Resource implements AutoCloseable { 2 public void use() { 3 System.out.println("Using resource"); 4 } 5 @Override 6 public void close () { 7 System.out.println("Resource closed"); 8 } 9 } 10 public class Main { 11 public static void main(String [] args) { 12 try (Resource res = new Resource ()) { 13 res.use(); 14 } // O método close () é chamado automaticamente aqui 15 } 16 } 113 / 125
  • 115.
    Herança Múltipla Polimorfismo Polimorfismoem Python Nas linguagens modernas, polimorfismo se refere ao fato de que o compilador seja capaz de identificar em tempo de execução (durante a execução do programa) qual a subclasse, dentro de uma hierarquia de classes, que responderá a uma determinada chamada de método. 1 class Video: 2 def __init__(self, arquivo): 3 if not arquivo.endswith(self.ext): 4 raise Exception("Formato de vídeo Inválido") 5 self.arquivo = arquivo 114 / 125
  • 116.
    Herança Múltipla Polimorfismo Polimorfismoem Python 1 from arquivoVideo import * 2 class VideoMP4(Video): 3 ext = "mp4" 4 def reproduzir(self): 5 print("Reproduzindo {} como mp4".for mat(self.arquivo)) 6 class VideoAVI(Video): 7 ext = "avi" 8 def reproduzir(self): 9 print("Reproduzindo {} como avi".for mat(self.arquivo)) 10 class VideoMOV(Video): 11 ext = "mov" 12 def reproduzir(self): 13 print("Reproduzindo {} como mov".for mat(self.arquivo)) 115 / 125
  • 117.
    Herança Múltipla Polimorfismo Polimorfismoem Python 1 from videoMP4 import * 2 3 mp4 = VideoMP4("filme.mp4") 4 mp4.reproduzir () 5 avi = VideoAVI("filme.avi") 6 avi.reproduzir () 7 mov = VideoMOV("filme.mov") 8 mov.reproduzir () 9 #outro = VideoMP4 (" filme.avi") Saída Normal Reproduzindo filme.mp4 como mp4 Reproduzindo filme.avi como avi Reproduzindo filme.mov como mov 116 / 125
  • 118.
    Herança Múltipla Polimorfismo Polimorfismoem Python 1 from videoMP4 import * 2 3 outro = VideoMP4("filme.avi") Saída Normal Traceback (most recent call last): File "/home/ramos/googleDrive/inProgress/tu- torialPOO/latex/fontes/reproduz2.py", line 3, in <module> outro = VideoMP4("filme.avi") raise Exception("Formato de vídeo Inválido") Exception: Formato de vídeo Inválido 117 / 125
  • 119.
    Herança Múltipla Polimorfismo Polimorfismoem Python Duck Typing (Tipos dinâmicos) do Python provêm uma forma muito mais poderosa de polimorfismo que o apresentado pelas linguagens que usam tipos estáticos. Ou seja, no Python o polimorfismo ocorre de forma natural. 118 / 125
  • 120.
    Herança Múltipla Polimorfismo FunçõesVirtuais em Python • Python não possui funções virtuais no sentido tradicional de linguagens como C++. No entanto, devido ao suporte a herança e ao polimorfismo, o comportamento é semelhante. • Em Python, todos os métodos em uma classe base são virtualmente sobrescritos nas subclasses (por padrão). Isso significa que o método da subclasse será chamado, mesmo quando acessado por meio de uma referência à classe base. 119 / 125
  • 121.
    Herança Múltipla Polimorfismo Usandométodos virtuais em python 1 class Animal: 2 def make_sound(self): 3 print("qualquer som genérico") 4 class Dog(Animal): 5 def make_sound(self): 6 print("Woof!") 7 animal = Animal () 8 dog = Dog() 9 animal.make_sound () # Saída: Some generic sound 10 dog.make_sound () # Saída: Woof! 11 # Polimorfismo em ação 12 animal = Dog() # Referência da classe base aponta para uma sub classe 13 animal.make_sound () # Saída: Woof! 120 / 125
  • 122.
    Herança Múltipla Polimorfismo ClassesAbstratas em Python • Em Python, são implementadas com o módulo abc. • A verificação da obrigatoriedade de implementação de métodos abstratos ocorre em tempo de execução. 121 / 125
  • 123.
    Herança Múltipla Polimorfismo ClassesAbstratas em Python _079_abstrata.py 1 from abc import ABC, abstractmethod 2 # Definindo a classe abstrata 3 class Veiculo(ABC): 4 @abstractmethod 5 def ligar(self): 6 """Método abstrato que deve ser implementado pelas sub class es""" 7 pass 8 @abstractmethod 9 def desligar(self): 10 """Método abstrato que deve ser implementado pelas sub class es""" 11 pass 12 def descricao(self): 13 """Método concreto (opcional)""" 14 print("Isto e um veículo.") 122 / 125
  • 124.
    Herança Múltipla Polimorfismo ClassesAbstratas em Python _079_abstrata.py 15 # Sub classe concreta 16 class Carro(Veiculo): 17 def ligar(self): 18 print("Motor do Carro ligado.") 19 def desligar(self): 20 print("Motor do Carro desligado.") 21 # Outra sub classe concreta 22 class Moto(Veiculo): 23 def ligar(self): 24 print("Motor da moto ligado.") 25 def desligar(self): 26 print("Motor da moto desligado.") 123 / 125
  • 125.
    Herança Múltipla Polimorfismo ClassesAbstratas em Python _079_abstrata.py 27 print("Motor da moto desligado.") 28 # Tentativa de instanciar a classe abstrata 29 try: 30 Veiculo = Veiculo () # Isso gera um erro 31 except TypeError as e: 32 print(f"Erro gerado: {e}") 33 34 # Usando as sub class es concretas 35 Carro = Carro () 36 Carro.ligar () # Saída: Motor do Carroro ligado. 37 Carro.desligar () # Saída: Motor do Carroro desligado. 38 Carro.descricao () # Saída: Isto é um veículo. 39 40 Moto = Moto () 41 Moto.ligar () # Saída: Motor da moto ligado. 42 Moto.desligar () # Saída: Motor da moto desligado. 43 Moto.descricao () # Saída: Isto é um veículo. 124 / 125
  • 126.