segunda-feira, 7 de março de 2011

Closures do Java 8 no Scala

Há algum tempo li como será a implementação de Closures no Java 8. Basicamente, será um sintax sugar para não precisar criar uma anonymous inner class, implementando alguma interface que possui apenas um método.
Java já possui vários frameworks que se utilizam desse pseudo-closure e a vinda do Java 8 vai realmente facilitar a escrita do código.
Eu fiquei pensando em como já utilizar esse tipo de sintaxe, utilizando Scala, nos frameworks java já existentes. Vou dar um exemplo. Queria transformar um código:
interface TesteListener {
 void execute (String message);
}

public class RecebedorDeListener {
 TesteListener listener;
 public RecebedorDeListener(TesteListener listener){
  this.listener = listener;
 }
}

//Para criar um objeto dessa classe:
new RecebedorDeListener(new TesteListener() {
   @Override
   public void execute(String message) {
    System.out.println(message);
   }
  });
Em:
 new RecebedorDeListener((x:String) => {println(x)} );
Já tinha visto implementações utilizando herança (por exemplo, criando uma classe filha de RecebedorDeListener) adicionando métodos e construtores que recebiam os closures. Mas eu queria algo mais direto.
Em Scala existem os implicits. O compilador procura os erros de compilação do código e verifica se ele pode utilizar algum conversor implícito que corrija o mesmo. Para o código acima, é necessário um conversor implícito que converta uma closure do tipo (String) => Unit (leia-se: uma função que recebe um parâmetro String e não retorna nada, ou void, ou, no caso do Scala, Unit) para um objeto da interface TesteListener onde o método void execute(String message) execute a função passada. Para isso:
  implicit def closure2TesteListener(x: (String)=>Unit): TesteListener = 
   new TesteListener(){
    override def execute (s: String) = {x(s)}
     };
Esse conversor implícito permite o compilador converter a função x, passada como parâmetro, em um objeto do tipo TesteListener. Com ele é possível executar o código esperado e, de quebra, se houver algum método que também espere um objeto do tipo TesteListener, pode ser utilizada a sintaxe de closure.
Conclusão: Scala é uma linguagem muito poderosa. Implicits é um recurso da linguagem que pode ajudar bastante para esses casos de ajuste de algum framework Java para uma sintaxe mais Scala-like mas, como todo poder, deve ser usado com parcimônia.

0 comentários: