Polimorfismo, Classes abstratas e Interfaces: Fundamentos da POO em Java
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.
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.
public class OperacaoMatematica {
public double calcular(double x, double y){
return 0;
}
}
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.
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.
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.
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));
}
}
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.
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.
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;
}
}
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.
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”.
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!
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Vídeo