Buscar

PARADIGMAS DE PROGRAMAÇão

Prévia do material em texto

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.
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.
Figura 1. Representação de herança 
entre classes.
Animal
Cachorro Gato
Programação orientada a objetos: herança e polimorfismo2
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.
Figura 2. Representação da relação do tipo tem uma entre 
classes.
Estado Cidade
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.
3Programaçã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 polimorfismo4
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.
Figura 3. Representação de polimorfismo entre classes.
FormaGeometrica
Circulo
desenhar()
Quadrado Retangulo
desenhar()desenhar()
desenhar()
5Programaçã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 receberdiferentes 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 polimorfismo6
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 Veiculo {
 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;
 }
 }
} 
7Programaçã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.
Figura 4. Modelo de classes para situação proposta de um programa para uma escola.
Pessoa
nome: string
cpf: string
data_nascimento : Date
newAttr : integer
obterDescontoMensalidade(valor) 
Professor
salario : double
disciplina : String
Aluno
Matricula : String
Programação orientada a objetos: herança e polimorfismo8
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;
}
9Programaçã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 polimorfismo10
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
11Programaçã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.
Programação orientada a objetos: herança e polimorfismo12

Continue navegando