Polimorfismo, Classes abstratas e Interfaces: Fundamentos da POO em Java

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (12)  (0)

Veja neste artigo alguns dos conceitos fundamentais da Programação Orientada a Objetos: Polimorfismo, Classes Abstratas e Interfaces. Serão mostradas, além da teoria, exemplos de implementação na linguagem Java.

O objetivo deste artigo é apresentar alguns componentes fundamentais da Programação Orientada a Objetos: Polimorfismo, Classes Abstratas e Interfaces. Serão apresentados os conceitos e implementações na linguagem Java para facilitar o entendimento.

Polimorfismo

O polimorfismo permite que classes abstratas consigam receber comportamentos através de classes concretas. Por exemplo, um dispositivo USB, podemos considerar que o USB seria uma classe abstrata enquanto os dispositivos (Pen Driver, Ipad, Câmeras, etc) seriam as classes concretas. Ou seja, o USB é uma especificação que pode ter várias implementações com características diferentes.

A figura a seguir ilustra alguns exemplos de tipos de polimorfismo.

Exemplo de Polimorfismo

Figura 1: Exemplo de Polimorfismo

Sobrescrita de método

A seguir temos um exemplo onde uma classe Soma herda de uma outra OperacaoMatematica, sobrescrevendo seu método calcular para implementar a lógica adequada à sua função. A sobrescrita de métodos é muito utilizada na implementação de polimorfismo para que uma classe filha possa definir seu próprio comportamento, baseada na estrutura da classe mãe.

Listagem 1: Classe OperacaoMatematica

public class OperacaoMatematica {
	
	public double calcular(double x, double y){
		return 0;
	}
}

Listagem 2: Classe Soma herdando de OperacaoMatematica

public class Soma extends OperacaoMatematica {

	public double calcular(double x, double y){
		return x + y;
	}
}

Neste exemplo da Listagem 3 é mostrado porque o polimorfismo é conhecido como “possuir muitas formas”. No método “calculaOperacao” acontece o polimorfismo, pois quando invocado, o argumento do tipo “OperacaoMatematica” é diferente para cada operação.

Listagem 3: Classe Testadora de polimorfismo

public class TestaOperacaoMatematica {

	//EXECUTA A OPERACAO - COM POLIMORFISMO
	public static void calculaOperacao(OperacaoMatematica o, double x, double y){
		System.out.println(o.calcular(x, y));
	}
		
	public static void main(String[] args) {
		calculaOperacao (new Soma(), 2500, 200);
		calculaOperacao (new Multiplicacao(), 10, 10);
	}
}

Classes abstratas

Pode-se dizer que as classes abstratas servem como “modelo” para outras classes que dela herdem, não podendo ser instanciada por si só. Para ter um objeto de uma classe abstrata é necessário criar uma classe mais especializada herdando dela e então instanciar essa nova classe. Os métodos da classe abstrata devem então serem sobrescritos nas classes filhas.

Por exemplo, é definido que a classe “Animal” seja herdada pelas subclasses “Gato”, “Cachorro”, “Cavalo”, mas ela mesma nunca pode ser instanciada.

Listagem 4: Classe abstrata Conta

abstract class Conta {
	
	private double saldo;
	
	public void setSaldo(double saldo) {
		this.saldo = saldo;
	}
	
	public double getSaldo() {
		return saldo;
	}
	
	public abstract void imprimeExtrato();

}

No exemplo da Listagem 5, o método “imprimeExtrato()” tem uma annotation conhecida como @Override, significando que estamos sobrescrevendo o método da superclasse. Entende-se em que na classe abstrata “Conta” os métodos que são abstratos têm um comportamento diferente, por isso não possuem corpo. Ou seja, as subclasses que estão herdando precisam desse método mas não de forma genérica, aonde permite inserir as particularidades de cada subclasse.

Listagem 5: Classe ContaPoupanca

import java.text.SimpleDateFormat;
import java.util.Date;

public class ContaPoupanca extends Conta {

	@Override
	public void imprimeExtrato() {
		System.out.println("### Extrato da Conta ###");
		
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/aaaa HH:mm:ss");
		Date date = new Date();
		
		System.out.println("Saldo: "+this.getSaldo());
		System.out.println("Data: "+sdf.format(date));
		
	}
}

Listagem 6: Classe Testadora para classes abstratas

public class TestaConta {
	public static void main(String[] args) {
		Conta cp = new ContaPoupanca();
		cp.setSaldo(2121);
		cp.imprimeExtrato();

	}
}

Interfaces

As interfaces são padrões definidos através de contratos ou especificações. Um contrato define um determinado conjunto de métodos que serão implementados nas classes que assinarem esse contrato. Uma interface é 100% abstrata, ou seja, os seus métodos são definidos como abstract, e as variáveis por padrão são sempre constantes (static final).

Uma interface é definida através da palavra reservada “interface”. Para uma classe implementar uma interface é usada a palavra “implements”, descrita na Listagem 8.

Como a linguagem Java não tem herança múltipla, as interfaces ajudam nessa questão, pois bem se sabe que uma classe pode ser herdada apenas uma vez, mas pode implementar inúmeras interfaces. As classes que forem implementar uma interface terão de adicionar todos os métodos da interface ou se transformar em uma classe abstrata, veja nos exemplos abaixo.

Na Listagem 7 a interface Conta tem seus métodos sem corpo, apenas com os parâmetros e o tipo de retorno.

Listagem 7: Declaração de uma interface

interface Conta{
	void depositar(double valor);
	void sacar(double valor);
	double getSaldo();
}

Neste exemplo da Listagem 8 os métodos são sobrepostos através da interface Conta.

Listagem 8: Classe Conta Corrente

public class ContaCorrente implements Conta {
	private double saldo;
	private double taxaOperacao = 0.45;
	
	@Override
	public void deposita(double valor) {
		this.saldo += valor - taxaOperacao;
	}

	@Override
	public double getSaldo() {
		return this.saldo;
	}

	@Override
	public void sacar(double valor) {
		this.saldo -= valor + taxaOperacao;
	}

}

Listagem 9: Classe ContaPoupanca com os métodos sobrepostos da interface Conta

public class ContaPoupanca implements Conta {
	private double saldo;
	
	@Override
	public void deposita(double valor) {
		this.saldo += valor;		
	}

	@Override
	public double getSaldo() {
		return this.saldo;
	}

	@Override
	public void sacar(double valor) {
		this.saldo -= valor;
		
	}

}

O método “geradorConta”, da Listagem 10, mostra a entrada de um parâmetro do tipo Conta, essa função será útil para a saída de um resultado.

Listagem 10: Classe GeradorExtratos

public class GeradorExtratos {
	
	public void geradorConta(Conta conta){
		System.out.println("Saldo Atual: "+conta.getSaldo());
	}

}

Na Listagem 11 são instanciadas as classes e o gerador de extratos. Na classe “GeradorExtratos” é invocado o método que aceita como parâmetro um tipo de “Conta”.

Listagem 11: Classe TestaContas

public class TestaContas {

	public static void main(String[] args) {
		
		ContaCorrente cc = new ContaCorrente();
		cc.deposita(1200.20);
		cc.sacar(300);

		ContaPoupanca cp = new ContaPoupanca();
		cp.deposita(500.50);
		cp.sacar(25);
		
		
		GeradorExtratos gerador = new GeradorExtratos();
		gerador.geradorConta(cc);
		gerador.geradorConta(cp);
	}

}

Conclusão

Neste artigo foram abordadas muita teoria e prática referentes às classes abstratas e polimorfismo. Espero que tenham gostado e até a próxima!

Acessem o space: Thiago Vinícius Varallo Palmeira.


 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?