Notícias
recent

Java Interface: Aprenda a usar corretamente

O uso de Interfaces em Java por muitas vezes é feito de forma errada, ou mesmo nem utilizado. Este artigo tem como principal objetivo demonstrar os usos práticos de Interfaces em Java.

Antes de tudo é importante entender qual o conceito principal de Interface: Esta tem objetivo criar um “contrato” onde a Classe que a implementa deve obrigatoriamente obedecer. Na listagem 1 vemos como criar uma simples Interface em Java.

Listagem 1: Minha primeira Interface


public interface MinhaPrimeiraInterface {

	/* Métodos que obrigatoriamente devem ser implementados pela
	 * Classe que implementar esta Interface 
	 */
	public void metodo1();
	public int metodo2();
	public String metodo3(String parametro1);

}

Perceba que os métodos na interface não têm corpo, apenas assinatura. Agora temos um “contrato” que deve ser seguido caso alguém a implemente. Veja na listagem 2, uma classe que implementa a nossa Interface acima.

Listagem 2: Implementando a Interface


public class MinhaClasse implements MinhaPrimeiraInterface {

	@Override
	public void metodo1() {
	// TODO Auto-generated method stub
	}

	@Override
	public int metodo2() {
	// TODO Auto-generated method stub
	return 0;
	}

	@Override
	public String metodo3(String parametro1) {
	// TODO Auto-generated method stub
	return null;
	}

	/**
	* @param args
	*/
	public static void main(String[] args) {
	// TODO Auto-generated method stub
	}

}

Ao usar a palavra reservada “implements” na MinhaClasse, você verá que a IDE (Eclipse, Netbeans e etc) obriga você a implementar os métodos descritos na Interface.

Usos Práticos da Interface


Tendo conhecimento do uso básico de uma Interface, podemos entender qual a verdadeira funcionalidade dela em um caso real.

Seguindo o Padrão


A Interface é muito utilizada em grandes projetos para obrigar o programador a seguir o padrão do projeto, por esta tratar-se de um contrato onde o mesmo é obrigado a implementar seus métodos, ele deverá sempre seguir o padrão de implementação da Interface.

Vamos supor o seguinte caso: Temos uma Interface BasicoDAO que dirá aos programadores do nosso projeto o que suas classes DAO devem ter (para efeito de conhecimento, o DAO é onde ficará nosso CRUD), qualquer método diferente do que tem na nossa Interface DAO será ignorado e não utilizado.

Listagem 3: Nossa Interface DAO


import java.util.List;

public interface BasicoDAO {

	public void salvar(Object bean);
	public void atualizar(Object bean);
	public void deletar(int id);
	public Object getById(int id);
	public List<Object> getAll();

}

Agora um dos programadores que está trabalhando no módulo de RH quer criar um DAO para realizar o CRUD de Funcionários, ele implementa a Interface acima e ainda adiciona métodos a parte (que serão ignorados mais a frente).

Listagem 4: Implementado a Interface DAO


import java.util.List;

public class FuncionarioDAO implements BasicoDAO {
	
	@Override
	public void salvar(Object bean) {
	// TODO Auto-generated method stub
	}

	@Override
	public void atualizar(Object bean) {
	// TODO Auto-generated method stub
	}

	@Override
	public void deletar(int id) {
	// TODO Auto-generated method stub
	}

	@Override
	public Object getById(int id) {
	// TODO Auto-generated method stub
	return null;
	}

	@Override
	public List<Object> getAll() {
	// TODO Auto-generated method stub
	return null;
	}

	//Método a parte criado e implementado pelo próprio programador
	public void calcularSalario(){
	}

}

Temos agora todos os itens da “receita”, vamos agora utilizá-lo em nossa aplicação. Suponha que um novo programador (que não criou a classe FuncionarioDAO), precise inserir um novo funcionário.

Este novo programador não tem idéia de como foi implementada a classe FuncionarioDAO, ele nem mesmo tem acesso a esta classe, porém ele sabe de algo muito mais importante: A Definição da Interface. Sendo assim ele irá usar todo o poder do polimorfismo e criar um novo objeto FuncionarioDAO do tipo BasicoDAO. Veja a listagem 5.

Listagem 5: Usando o polimorfismo


public class MeuApp {
	/**
	* @param args
	*/
	public static void main(String[] args) {
		BasicoDAO funcionarioDAO = new FuncionarioDAO();
		funcionarioDAO.salvar(new Funcionario());
	}
}

Perceba que criamos o objeto FuncionarioDAO do tipo BasicoDAO, sendo assim só conseguimos chamar os métodos da Interface BasicoDAO. Mas o mais importante é que o novo programador que utilizará a classe FuncionarioDAO, poderá chamar os métodos descritos na Interface.

Mas o que obriga que o programador que criou a classe FuncionarioDAO implemente BasicoDAO ? Na verdade nada, ele pode criar FuncionarioDAO sem implementar a interface, porém o novo programador que utilizará essa classe não conseguirá realizar o polimorfismo acima e verá que a classe está errada, foi criada de forma errada, fora do padrão. Há ainda outra forma de sabermos se a classe que foi criada implementou a interface BasicoDAO, veja na listagem 6.

Listagem 6: Uso do instanceof


public class MeuApp {
	/**
	* @param args
	*/
	public static void main(String[] args) {
		FuncionarioDAO funcionarioDAO = new FuncionarioDAO();
		if (funcionarioDAO instanceof BasicoDAO) {
			funcionarioDAO.salvar(new Funcionario());
		} else {
			System.err.println("A Classe FuncionarioDAO não" + 
				"implementa BasicoDAO, nenhum procedimento foi realizado");
		}
	}
}

Agora conseguimos ver os métodos implementados a parte pelo programador (fora da implementação da interface), porém testamos antes se a classe é uma instancia (instanceof) de BasicoDAO.

Interface de Marcação


Existe ainda um conceito que chamamos de: Interface de Marcação. São interfaces que servem apenas para marcar classes, de forma que ao realizar os “instanceof” podemos testar um conjunto de classe.

Vamos a outro exemplo prático: Temos uma Interface Funcionario sem nenhum método ou atributo, isso porque será apenas uma interface de marcação. Veja na listagem 7.

Listagem 7: Interface de Marcação Funcionario


public interface Funcionario {
}

Agora criamos 3 Beans, que correspondem a 3 tipos distintos de funcionários: Gerente, Coordenador e Operador. Todos implementando Funcionario.

Listagem 8: Criação de Gerente, Coordenador e Operador

public class Gerente implements Funcionario {
	private int id;
	private String nome;
}

public class Coordenador implements Funcionario {
	private int id;
	private String nome;
}

public class Operador implements Funcionario {
	private int id;
	private String nome;
}

Agora em nossa aplicação temos um método que realiza um procedimento de calculo de salário diferente para cada tipo de funcionário. Poderiamos não utilizar o poder da Interface e fazer a implementação abaixo.

Listagem 9: Uso indevido da Interface de Marcação


public class MeuApp {
	public void calcSalarioParaGerente(Gerente gerente){}
	
	public void calcSalarioParaCoordenador(Coordenador coordenador){}

	public void calcSalarioParaOperador(Operador operador){}
}

Muito trabalho pode ser reduzido a apenas 1 método, mostrado na listagem 9.

Listagem 10: Usando a interface de marcação


public class MeuApp {
	public void calculaSalarioDeFuncionario(Funcionario funcionario) {
		if (funcionario instanceof Gerente) {
		//calculo para gerente
		} else if (funcionario instanceof Coordenador) {
		//calculo para coordenador
		} else if (funcionario instanceof Operador) {
		//calculo para operador
		}
	}
}

Em vez de ficar criando um método para cada tipo de funcionário, juntamos tudo em apenas 1 utilizando a interface de marcação.

CONCLUSÃO


Quando bem utilizada, a interface acaba tornando-se uma poderosa ferramenta nas mãos de um programador ou Analista, e torna-se indispensável o seu uso no dia-a-dia. As boas práticas de programação regem que o uso da Interface é indispensável para um bom projeto de software.

FONTE: DevMode
Laisson R. Silveira

Laisson R. Silveira

Louco por inovações e desenvolvimento de softwares, apaixonado por música e praia. Analista Desenvolvedor Java e Consultor de Sistemas.

Formulário de contato

Nome

E-mail *

Mensagem *

Tecnologia do Blogger.