Você está na página 1de 27

Programação orientada a objetos:

herança e polimorfismo

APRESENTAÇÃO

A reusabilidade de código é uma das grandes vantagens do desenvolvimento de softwares em


linguagens de programação orientada a objetos. Pela estrutura de classes e construção de
programas, pensando em abstrair entidades da realidade para o conceito de objetos, é possível
que os códigos se tornem mais organizados e reutilizáveis.
Quando se pensa em reusabilidade de código em orientação a objetos, é necessário
conhecer como funciona o conceito de herança e polimorfismo.

Nesta Unidade de Aprendizagem, você conhecerá o conceito e tipos de herança e polimorfismo


na visão da orientação a objetos e também como são aplicados, utilizando exemplos em
linguagem de programação orientada a objetos.

Bons estudos.

Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:

• Especificar a herança na orientação a objetos.


• Discutir o polimorfismo na orientação a objetos.
• Aplicar a herança e o polimorfismo.

DESAFIO

A herança é um conceito da programação orientado a objetos que permitem o reuso de código.


Por meio do conceito de herança, novas classes são criadas a partir de classes já existentes,
absorvendo os seus atributos e métodos e adicionando os seus próprios.

A partir disso, considere a seguinte situação:

Conteúdo interativo disponível na plataforma de ensino!


Com base em tais informações e utilizando o conceito de herança, apresente o modelo de classes
e o modelo descritivo com os atributos e métodos das classes necessárias para atender a esse
requisito. Utilize os métodos 'get' e 'set' para manipulação dos atributos de cada classe.

INFOGRÁFICO

O conceito de herança é um dos conceitos base da programação orientada a objetos. Qualquer


linguagem de programação que implemente o paradigma de orientação a objetos deve permitir
que a herança seja implementada.

Neste Infográfico, você verá a sintetização de conceitos relacionados à herança entre classes,
abordando a hierarquia de classes, herança simples e herança múltipla.
CONTEÚDO DO LIVRO

A programação orientada a objetos, sem dúvida, possibilitou que os programas de computadores


ficassem mais próximos da realidade. Avanços relacionados à criação de programas em
linguagens orientadas a objetos vão desde a facilidade de acoplação até mesmo a manutenção de
sistemas.

Outro benefício importante da programação orientada a objetos está ligado ao reuso de código.
E, quando se fala em reuso de código em programação orientada a objetos, é necessário falar
sobre herança e polimorfismo.

No capítulo Programação orientada a objetos: herança e polimorfismo, da obra Paradigmas de


programação, base teórica desta Unidade de Aprendizagem, você vai conhecer mais sobre esses
conceitos da programação orientada a objetos, entender os tipos de herança e as formas de
implementação de polimorfismo em linguagens orientadas a objetos.

Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO

Fabricio Machado da Silva


Programação orientada
a objetos: herança
e polimorfismo
Objetivos de aprendizagem
Ao final deste texto, você deverá apresentar os seguintes aprendizados:

„„ Especificar a herança na orientação a objetos.


„„ Discutir o polimorfismo na orientação a objetos.
„„ Aplicar a herança e o polimorfismo.

Introdução
O paradigma da programação orientada a objetos surgiu com o intuito
de aplicar conceitos da realidade ao contexto da programação de com-
putadores. O próprio nome, orientação a objetos, remete ao conceito
de que o foco da construção dos programas está em orientar a estrutura
para as entidades objetos, que emulam noções existentes no mundo real.
Para que o paradigma de orientação a objetos tenha maior abrangên-
cia, faz-se necessário que outros conceitos também sejam possíveis e,
nesse escopo, ocorre a herança entre objetos. Assim como na realidade,
no contexto da programação orientada a objetos, a herança está asso-
ciada à característica de possuir comportamentos de outra entidade.
Neste capítulo, iremos entender o funcionamento do conceito de
herança na programação orientada a objetos. Além disso, abordaremos
o conceito de polimorfismo, que permite que a herança entre objetos
seja possível, mesmo com alterações no comportamento herdado, para
atender a características específicas do objeto herdeiro.
2 Programação orientada a objetos: herança e polimorfismo

O conceito de herança na orientação a objetos


O conceito de herança na programação orientada a objetos é utilizado para
se permitir a reutilização de um código. A herança possibilita que classes
compartilhem seus atributos e métodos entre si. Segundo Tucker e Noonan
(2009, p. 335),

[...] o paradigma orientado a objetos suporta reutilização de código por in-


termédio da herança. As classes existem em uma linguagem orientada a
objetos em uma hierarquia de classes. Uma classe pode ser declarada como
uma subclasse de outra classe, que é chamada de classe mãe ou superclasse.

Dentro dessa relação de hierarquia de classes é possível que a subclasse


herde atributos e comportamentos da superclasse, simplesmente pelo fato de
ser sua subordinada.
Na programação orientada a objetos, a relação de herança entre classes é
a relação em que uma classe é do tipo é uma, e não do tipo tem uma. Esta é
uma das confusões recorrentes na construção de programas em orientação
a objetos.
Para ilustrar essa diferença, observe a Figura 1 e veja que, neste exemplo,
temos um tipo de relação é uma, pois o objeto da classe Cachorro, assim
como o objeto da classe Gato, é, por herança, um tipo de objeto da classe
Animal.

Animal

Cachorro Gato

Figura 1. Representação de herança


entre classes.
Programação orientada a objetos: herança e polimorfismo 3

Compare, agora, a relação apresentada na Figura 2, que representa uma


relação do tipo tem uma. Perceba que, neste caso, uma relação de herança
entre as classes Estado e Cidade não faz sentido, visto que um estado
possui cidades, mas uma cidade não é um estado.

Estado Cidade

Figura 2. Representação da relação do tipo tem uma entre


classes.

No conceito de herança, a superclasse geralmente é uma classe genérica,


que engloba os atributos e métodos que podem ser utilizados por qualquer
classe herdeira. Não faz sentido utilizar a superclasse para atribuir, por exem-
plo, um atributo ou método que seja específico de uma subclasse, pois, neste
caso, todas as demais subclasses estariam herdando este atributo ou método
desnecessariamente.
A herança pode apresentar duas formas diferentes. A mais comum e uti-
lizada pelas linguagens de programação, em geral, é a herança simples. No
entanto, algumas linguagens de programação orientada a objetos, como a
linguagem C++ e Python, possibilitam a implementação da herança múltipla
(TUCKER; NOONAN, 2009).
Na herança simples, uma hierarquia de classe forma uma árvore, com
sua raiz na classe genérica. Uma classe D é uma subclasse de outra classe
C quando ela estende ou especializa o significado da classe C e acrescenta
novas variáveis de instância ou métodos, ou quando modifica as definições
dos métodos público e protegido de C.
A herança múltipla, conforme já mencionado, é um recurso que também
pode ser implementado por algumas linguagens de programação orientada
a objetos. A linguagem Java, por exemplo, uma das linguagens orientada a
objetos mais utilizadas não permite a implementação da herança múltipla.
Em contraposição à herança simples, na herança múltipla uma classe pode
herdar atributos e métodos de mais de uma superclasse, atribuindo a esta
comportamentos de diferentes classes.
4 Programação orientada a objetos: herança e polimorfismo

Existem situações em que seu uso pode ser pertinente, mas a herança múl-
tipla também possui desvantagens, especialmente em razão de sua semântica,
que pode dificultar a manutenção do código. Conforme Lima (2014, p. 148)
observa,

[...] uma desvantagem da herança múltipla é que sua semântica se torna muito
complicada em certas circunstâncias. Por exemplo, se uma classe E tem sub-
classes B e C, e um método M é definido diferentemente em B e C, que imple-
mentação de M deveria ser herdada por E: aquela em B, aquela em C ou ambas?

Em alguns casos é necessário que a subclasse possua um comportamento


diferenciado do que foi herdado da superclasse. Na orientação a objetos, cha-
mamos esse conceito de polimorfismo. Na próxima seção, iremos abordá-lo
no contexto da orientação a objetos.

Polimorfismo
O polimorfismo na programação orientada a objetos permite que uma ou mais
classes derivadas de uma mesma superclasse possam invocar métodos que
possuam uma mesma assinatura, mas com comportamentos diferenciados
para cada classe derivada, utilizando, para isso, uma referência a um objeto
da superclasse.
A definição de polimorfismo é mais um dos recursos da orientação a
objetos que possibilita que um comportamento encontrado na realidade seja
aplicado à programação. Na natureza, existem animais que são capazes de
modificar sua forma ou comportamento para atender a determinada situação,
e é isto que o polimorfismo possibilita na programação orientada a objetos.
Segundo Tucker e Noonan (2009, p. 323), “em linguagens orientadas a ob-
jetos, polimorfismo refere-se à ligação tardia de uma chamada a uma ou várias
diferentes implementações de um método em uma hierarquia de herança”.
Para entendermos melhor este exemplo, suponhamos que uma aplicação
implementa um programa de desenho. Em um programa desses, podemos ter
diferentes formas geométricas: círculo, quadrado, retângulo etc.
Programação orientada a objetos: herança e polimorfismo 5

Cada uma das formas geométricas é representada, respectivamente, por


uma das classes apontadas a seguir.

„„ classe circulo;
„„ classe quadrado;
„„ classe retangulo.

Todas essas classes são subclasses da classe FormaGeometrica. Temos,


na superclasse FormaGeometrica, a definição do método desenhar,
mas sabemos que desenhar um círculo é diferente de desenhar um retângulo.
Neste caso, a forma de implementar o método desenhar na subclasse
Circulo deve possuir um comportamento diferente da implementação
na subclasse Retangulo, apesar de todas herdarem e necessitarem dessa
implementação. Portanto, o conceito de polimorfismo serve justamente para
resolver questões como esta.
A Figura 3 ilustra um diagrama de classes com base nesta implementação.

FormaGeometrica

desenhar()

Circulo Retangulo
Quadrado

desenhar() desenhar() desenhar()

Figura 3. Representação de polimorfismo entre classes.


6 Programação orientada a objetos: herança e polimorfismo

Para Lima (2014), são dois os tipos mais recorrentes de polimorfismo na


programação orientada a objetos:

a)  polimorfismo estático ou sobrecarga de método;


b)  polimorfismo dinâmico ou sobrescrita de método.

O polimorfismo estático ou sobrecarga de método é a forma de implemen-


tação em que são definidos vários métodos com o mesmo nome, mas com
assinaturas diferentes. Ou seja, cada método pode receber diferentes parâmetros
ou, então, os mesmos parâmetros de tipos diferentes. A sobrecarga consiste
em permitir, dentro da mesma classe, mais de um método com o mesmo nome.
Entretanto, eles devem necessariamente possuir argumentos diferentes para
funcionar. Booch, Rumbaugh e Jacobson (2006) afirmam que a escolha de
qual método irá ser chamado pelo programa principal dependerá do seu tipo
de objeto, e esta decisão será tomada apenas no tempo de execução, por meio
de ligação tardia.
Veja o exemplo a seguir de um código em linguagem Java para uma classe
Calculadora. Perceba que o método calcula aparece três vezes: o primeiro
recebe como parâmetro dois valores int, o segundo recebe dois valores
double e o terceiro recebe dois valores String.

public class Calculadora {


public int calcula(int a, int b) {
return a+b;
}
public double calcula(double a, double b) {
return a+b;
}
public String calcula(String a, String b) {
return a+b;
}
}

O polimorfismo dinâmico ou sobrescrita de método nos permite reescrever


um método, ou seja, podemos reescrever nas subclasses os métodos criados
inicialmente na superclasse. Os métodos que serão sobrepostos, diferentemente
dos sobrecarregados, devem possuir o mesmo nome, tipo de retorno e quan-
tidade de parâmetros do método inicial. No entanto, este será implementado
Programação orientada a objetos: herança e polimorfismo 7

com especificações da classe atual, podendo adicionar algo a mais ou não


(LIMA, 2014).
Para ilustrar este exemplo, vamos novamente utilizar um trecho de código
de uma classe em linguagem Java. Primeiramente, observe a escrita do método
setVelocidade na superclasse Veiculo:

public abstract class Veiculo {


public float velocidade;
public void setVelocidade(float v) {
velocidade = v;
}
}

Veja, então, como ficaria a implementação na subclasse Carro. Observe


que a assinatura do método é a mesma da superclasse, ou seja, recebe v como
parâmetro do tipo float. Porém, na subclasse, além de atribuir o valor de v
para velocidade, são feitos um tratamento e uma atribuição de valor ao atributo
marcha, dependendo da velocidade do veículo.

public abstract class Carro. {


public float velocidade;
public void setVelocidade(float v) {
velocidade=v;
if (velocidade < 20){
marcha = 1;
} else if (velocidade >= 20 && velocidade < 40) {
marcha = 2;
} else if (velocidade >= 40 && velocidade < 60){
marcha = 3;
} else if (velocidade >= 60 && velocidade < 70){
marcha = 4;
} else if (velocidade >= 70){
marcha = 5;
}
}
}
8 Programação orientada a objetos: herança e polimorfismo

Na próxima seção, iremos abordar um exemplo de aplicação de herança e


polimorfismo em linguagens orientadas a objetos.

Aplicação de herança e polimorfismo


Nas seções anteriores, abordamos os conceitos de herança e polimorfismo em
programação orientada a objetos, utilizando a linguagem de programação Java.
Nesta seção, iremos apresentar a implementação destes conceitos na constru-
ção de um programa para uma escola, no qual são utilizados os exemplos de
herança entre as classes Professor e Aluno, que herdam de Pessoa, e o
polimorfismo dinâmico, para o método obterDescontoMensalidade,
que calcula o valor da mensalidade com desconto. A Figura 4 ilustra o modelo
de classes para esta situação.

Pessoa
nome: string
cpf: string
data_nascimento : Date
newAttr : integer

obterDescontoMensalidade(valor)

Professor
Aluno
salario : double
Matricula : String
disciplina : String

Figura 4. Modelo de classes para situação proposta de um programa para uma escola.
Programação orientada a objetos: herança e polimorfismo 9

Primeiramente, vamos ver como ficaria a construção da superclasse


Pessoa.

public class Pessoa {


public String nome;
public String cpf;
public Date data _ nascimento;
public Pessoa (String _ nome, String _ cpf, Date _ data) {
this.nome = _ nome;
this.cpf = _ cpf;
this.data _ nascimento = _ data;
}
}

Após a criação da superclasse, vamos verificar os códigos utilizado para


a criação das subclasses Aluno e Professor. Certifique-se de que sua
declaração inclua as palavras extends Pessoa depois de Aluno. Essa
sintaxe é da linguagem Java e significa que as subclasses devem herdar da
superclasse Pessoa.

public class Aluno extends Pessoa {


public Aluno (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public String matricula;
}

public class Professor extends Pessoa {


public Professor (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public double salario;
public String disciplina;
}
10 Programação orientada a objetos: herança e polimorfismo

Podemos verificar que, tanto na subclasse Aluno, quanto na subclasse


Professor, o método construtor está utilizando os atributos que foram
declarados na superclasse Pessoa:

_ nome
_ cpf
_ data

Além disso, observe que no caso da subclasse Aluno é definido um atributo


específico matricula, que só faz sentido para Aluno. No caso da subclasse
Professor, os atributos salario e disciplina só fazem sentido no
contexto de Professor.
Estes exemplos ilustram o típico uso de herança, sem haver necessidade
de reescrever nas subclasses o que é comum a elas, escrevendo somente o
que lhes é específico.
Agora, suponhamos que a escola resolveu criar um programa de oferta
de descontos em mensalidades para Aluno e para Professor. Contudo, a
diferença de percentual seria de 20% para os professores e apenas 10% para
alunos. Vamos adotar o desconto de 10% como o desconto comum, logo, seria
criado na superclasse Pessoa o método obterDescontoMensalidade
para retornar o valor do desconto. Dessa forma, não é necessário fazer nenhuma
alteração na subclasse Aluno, pois o comportamento será automaticamente
herdado da superclasse Pessoa.

public class Pessoa {


public String nome;
public String cpf;
public Date data _ nascimento;
public Pessoa (String _ nome, String _ cpf, Date _ data) {
this.nome = _ nome;
this.cpf = _ cpf;
this.data _ nascimento = _ data;
}
public double obterDescontoMensalidade (double valor) {
//Retorna o valor do desconto na mensalidade
return 0.10 * valor;
}
}
Programação orientada a objetos: herança e polimorfismo 11

Como especificado na regra de negócio, os objetos da classe Professor


devem receber um desconto diferenciado de 20%. Logo, utilizando o conceito
de polimorfismo dinâmico, em que o método possui a mesma assinatura,
apenas implementando um novo comportamento, vamos fazer um ajuste para
atender a esta necessidade.
Veja, então, como ficaria a subclasse Professor:

public class Professor extends Pessoa {


public Professor (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public double salario;
public String disciplina;
public double obterDescontoMensalidade (double valor) {
//Retorna o valor do desconto na mensalidade
return 0.20 * valor;
}
}

Este foi um exemplo de aplicação simples da utilização em uma mesma


estrutura de classes dos conceitos apresentados neste capítulo. Por fim, é
possível verificar que herança e polimorfismo se relacionam no contexto das
linguagens de programação orientada a objetos.

Acesse o link a seguir para um exemplo de polimorfismo e herança em Python, uma


importante linguagem de programação que permite a orientação a objetos.

https://qrgo.page.link/6xYCs
12 Programação orientada a objetos: herança e polimorfismo

BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. 2. ed. Rio de Janeiro:
Elsevier; Campus, 2006. 474 p.
LIMA, A. S. UML 2.5: do requisito à solução. São Paulo: Érica, 2014. 368 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.

Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
DICA DO PROFESSOR

Existem dois tipos básicos de implementação do conceito de polimorfismo em linguagens


orientadas a objetos. Pode ser usado o formato de implementação estática ou sobrecarga de
métodos ou então o formato de implementação dinâmica ou sobrescrita de método. Qualquer um
dos formatos é encontrado.

Nesta Dica do Professor, você irá entender o conceito de polimorfismo para que seja possível
diferenciar cada um dos seus tipos de implementação.

Conteúdo interativo disponível na plataforma de ensino!

EXERCÍCIOS

1) Ao analisar um modelo de classes de um sistema, você identificou que existe um


relacionamento de herança entre as classes MeioPagamento e CartaoCredito, sendo a
classe mãe a MeioPagamento e a classe herdeira a CartaoCredito. Sobre essa
situação, assinale a alternativa correta:

A) Somente atributos public da classe MeioPagamento serão herdados pela classe


CartaoCredito.

B) Todos os atributos da classe MeioPagamento serão herdados pela classe CartaoCredito.

C) Todos os atributos serão herdados da classe MeioPagamento, mas os métodos não serão.

D) Todos os atributos serão herdados, mas novos atributos inseridos na classe


MeioPagamento não serão.

E) Não será possível criar um objeto a partir da classe CartaoCredito sem antes criar objeto
MeioPagamento.
2) Utilizando ainda o exemplo do exercício anterior, caso existisse a necessidade de
inserir um atributo para armazenar o valor do limite de gastos diários, que seria
único por CartaoCredito, lembrando que a classe MeioPagamento também tem como
herdeira a classe CartaoDebito, assinale a alternativa correta sobre essa
implementação:

A) O atributo limiteGastosDiario seria criado somente na classe CartaoCredito.

B) O atributo limiteGastosDiario seria criado na classe CartaoCredito e MeioPagamento.

C) O atributo limiteGastosDiario seria criado somente na classe MeioPagamento

D) O atributo limiteGastosDiario seria criado na classe MeioPagamento, CartaoCredito e


CartaoDebito.

E) O atributo limiteGastosDiario seria criado na classe MeioPagamento e CartaoCredito, mas


os métodos get e set somente na MeioPagamento.

3) Em algumas linguagens de programação orientada a objetos, como C++ e Python, é


possível que uma classe possua relacionamento de herança com mais de uma classe.
Assinale a alternativa correta quanto ao nome desse tipo de herança:

A) Herança Composta.

B) Herança Associativa.

C) Herança Dupla.

D) Herança Múltipla.
E) Herança Binária.

4) Em herança entre classes, existe a possibilidade de uma classe herdeira reescrever


um método implementado pela classe mãe. Dessa forma, a classe herdeira atribui um
comportamento diferenciado ao da classe mãe, sendo o nome desse conceito
polimorfismo. Assinale a alternativa correta sobre o polimorfismo:

A) Só é possível aplicar polimorfismo quando os métodos têm a mesma assinatura.

B) O polimorfismo é um recurso mais recente que a herança na orientação a objetos.

C) Em herança múltipla, não é possível aplicar o conceito de polimorfismo, apenas em


herança simples.

D) O polimorfismo só permite a alteração de escopo de um método da superclasse pela


subclasse.

E) O polimorfismo é uma característica em orientação a objetos que usa a hierarquia de


objetos.

5) Existem duas formas de implementação de polimorfismo. Uma se dá quando se tem a


mesma operação implementada várias vezes na mesma classe e a outra acontece na
herança, quando a classe herdeira altera o método original. Assinale a alternativa
correta quanto ao nome desses tipos de implementação de polimorfismo:

A) Sobrecarga e Sobreposição.

B) Estático e Sobrecarga.

C) Dinâmico e Sobreposição.
D) Alternativo e Sobrecarga.

E) Alternativo e Sobreposição.

NA PRÁTICA

A herança, o polimorfismo e a reutilização de código estão relacionados em programação


orientada a objetos. Quando se fala de herança entre classes, fala-se implicitamente de
reutilização de código, pois herdar é minimizar a escrita de código. O polimorfismo entra como
recurso interessante que permite que apenas aqueles métodos que devem se comportar de forma
diferenciada em uma classe herdeira sejam reescritos sem a necessidade de reescrita total de
uma classe.

A herança é um conceito muito poderoso, uma vez possibilitar que os desenvolvedores


maximizem o uso dos métodos (comportamento) e dos dados (estrutura) dos objetos existentes.
Já o polimorfismo é a habilidade de objetos receberem a mesma mensagem e comportarem-se
de maneira diferente.

Neste Na Prática, você verá um exemplo da utilização de herança e polimorfismo em uma


aplicação escrita em Java para entender como esses conceitos se relacionam com o objetivo de
reduzir a necessidade de reescrita de código.
SAIBA +

Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:

Herança na programação orientada a objetos

Neste vídeo, você entenderá, de forma bem didática, sobre o conceito de herança na
programação orientada a objetos.

Conteúdo interativo disponível na plataforma de ensino!

Conceituando polimorfismo

Para conhecer mais sobre o conceito de polimorfismo na programação orientada a objetos,


assista ao vídeo a seguir.

Conteúdo interativo disponível na plataforma de ensino!

Herança Múltipla com Python

Assista ao vídeo a seguir e conheça a aplicação do conceito de Herança Múltipla, utilizada na


linguagem de programação Python.

Conteúdo interativo disponível na plataforma de ensino!

Você também pode gostar