Baixe o app para aproveitar ainda mais
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
Compartilhar