Interfaces Funcionais
Não é magia é tecnologia..ops! Entenda o que é e como funciona uma Interface Funcional do Java 8
Olá, vimos no artigo anterior sobre Lambda, uma pequena introdução sobre Expressões Lambda e como ela pode ser utilizada no Java 8 e vimos a sua estrutura básica etc. Mas algo ficou meio que misterioso, afinal como essa mágica acontece?
Como podemos ter uma linguagem fortemente tipada e verbosa implementar algo como o Lambda que é muito forte em linguagens funcionais?
Sinto decepcioná-los, mas não é nenhuma magia ou algo ligado a forças do submundo ou algo do supernatural.
Lhes apresento a Interface Funcional.
Interface Funcional
Tudo é por causa do que chamamos de Interfaces Funcionais e neste artigo iremos entender mais o que é isso e o que muda ou não na estrutura da linguagem.
Primeiramente não se desespere, a Interface do Java continua sendo uma interface, nada mudou, não explicitamente. Lembre-se que o Java tem a retrocompatibilidade, então ele não poderia mudar a estrutura de uma forma que prejudique ou quebre qualquer versão anterior.
De uma maneira bem direta e grossa podemos dizer que:
"Interface Funcional é aquela Interface que possui apenas UM ÚNICO método abstrato."
Sim, apenas isso. Mas como algo "tão simples" pode ser tão poderoso?
Bem, sem o conceito de Interface Funcional o Lambda não seria -possível- no Java, não dessa forma que na minha opinião foi até elegante, afinal mais uma vez: -Java é verboso e "burocrático", e existem motivos bem FORTES para ela ser assim, mas isso falaremos em outro episódio ;).
Lembra do exemplo do artigo anterior onde fizemos um exemplo usando Collections?
Collections.sort(lista, new Comparator<String>(){
public int compare(String valor1, String valor2){
return valor1.length() - valor2.length();
}
});
Com Lambda:
Collections.sort(lista, (v1, v2) -> v1.length() - v2.length());
Adivinhe! O Comparator
é uma interface que possui apenas um método abstrato, ou seja, ela é uma Interface Funcional.
Mais um exemplo, imagine que queremos rodar um Runnable
:
Até a versão 7 do Java faríamos assim:
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Executando....");
}
};
Opa! O Runnable é uma Inferface e adivinha só....sim, ela possui apenas um método abstrato! Então quer dizer que podemos usar Lambda nele:
Agora com Java 8:
Runnable r = () -> { System.out.println("Executando...."); };
E ainda podemos por exemplo retirar as chaves {}
já que a expressão possui apenas um único comando o System.out.println()
:
Runnable r = () -> System.out.println("Executando....");
Você entendeu o que aconteceu? Com o conceito de Interface Funcional até as interfaces pré Java 8 você pode utilizar o Lambda, pois elas cumprem o pre-requisito básico, que é ter apenas um método abstrato, mantendo a retrocompatibilidade e ainda "adicionando" uma nova forma de fazer a mesma coisa com menos código.
E não é só isso, no Java 8 as interfaces ganharam outras "funcionalidades", uma delas é que agora é permitido ter métodos implementados, isso mesmo, porém ele precisa ser obrigatoriamente estático(static) ou default, mas isso falaremos no próximo post.
Basta ver a Comparator do Java 7 e a "nova" Comparator do Java 8, com vários métodos estáticos e implementados.
Interface Comparator JDK 7:
public interface Comparator<T> {
int compare(T o1, T o2);
}
Interface Comparator JDK 8:
@FunctionalInterface
public interface More ...Comparator<T> {
int compare(T o1, T o2);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
//....
}
Além disso foi incluído um novo pacote java.util.function
, com várias interfaces funcionais para você reaproveitar. Veremos algumas delas em outros posts.
Mas e se eu precisar criar algo? E vai que o Java não me deu nenhuma Interface Funcional específica para o que eu quero? Sim, você pode criar a sua....
Criando a nossa Interface Funcional
Vamos criar um exemplo simples, um Validador
onde vou poder implementar a validação de um CPF por exemplo, então crio a interface:
public interface Validador {
boolean validarCPF(String valor);
}
E para utilizar seria algo semelhante ao código abaixo, fazendo com classes anônimas:
Validador validar = new Validador() {
public boolean validarCPF(String valor) {
return valor.matches("(?!(\\d)\\1{10})\\d{11}");
}
};
Observe que a minha interface só possui um único método abstrato, então posso utilizá-la com Lambda:
Validador validarLambda = (v) -> v.matches("(?!(\\d)\\1{10})\\d{11}");
Pronto, criei minha Interface Funcional!
Mas e se chegar outro programador e criar por exemplo o validaCNPJ
?
public interface Validador {
boolean validarCPF(String valor);
boolean validaCNPJ(String valor);
}
Bem, na Interface nada acontece, afinal é apenas mais um método abstrato, porém devemos lembrar da regra básica do Lambda:
"-Só pode haver um!"
Na classe que estamos utilizando irá dar erro de compilação:
Observe que quando temos uma Interface com apenas um único método ela querendo ou não já é uma Interface Funcional, porém isso não é algo explicito, outro programador pode ir lá e adicionar um novo método ou mais e assim seu código irá quebrar.
Para evitar isso podemos anotar a nossa interface com o @FunctionalInterface
e ao fazer isso caso um outro programador tente colocar mais um método na interface o seguinte erro irá acontecer:
Invalid '@FunctionalInterface' annotation; Validador is not a functional interface;
Podemos observar que não há mistérios em criar uma Interface Funcional para usarmos as expressões lambda é simples e muito poderoso.
Interface Validador.
Classe Exemplo de uso.
Conclusão
Neste artigo conhecemos um pouco mais sobre o segredo de como o Java implementa as expressões lambda e algumas regras básica sobre a Interface Funcional.
Interface Funcionais são sim o coração do Lambda no Java até porque o Lambda por si só não existe, e sim EXPRESSÕES LAMBDA, isso quando elas são atribuídas a uma interface funcional.
Temos mais alguns conceitos para lhe passar, por exemplo: executar mais de uma instrução na expressão lambda, métodos defaults e claro melhorar a nossa interface Validador
;) então fica ligado nos próximos artigos que iremos te passar tudo isso.
Quer entender melhor a linguagem e a sua plataforma? E aprender Orientação a Objetos de verdade, aquela OO raiz, da várzea? Fica ligado nas próximas turmas de Java e Orientação a Objetos da TriadWorks ;)
Deixe seu comentário, dúvida, crítica e sugestões ;)
Abraços e bons estudos....
You might also be interested in these articles...
Desenvolvedor, Fundador da TriadWorks e da JavaCE
Posted in: cursoeclipseensinofortalezafuncionalfunctionalfunctional interfaceinterfaceinterface funcionaljavajava 8java eejeelogica de programacaoooorientação a objetospolimorfismotreinamentotutorial