Você está na página 1de 15

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.

Você também pode gostar