dimanche 6 janvier 2013

java 8 : Interfaces fonctionnelles


Dans cette article, nous allons aborder la notion des interfaces fonctionnelles. C'est le point d'entrée pour utiliser les nouvelles features de JAVA 8.

Definition de la JSR 335

A functional interface is an interface that has just one abstract method, and thus represents a single function contract. (In some cases, this "single" method may take the form of multiple abstract methods with override-equivalent signatures (8.4.2) inherited from superinterfaces; in this case, the inherited methods logically represent a single method.)
In addition to the usual process of creating an interface instance by declaring and instantiating a class, instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
The function descriptor of a functional interface I is a method type—type parameters, formal parameter types, return types, and thrown types—that can be used to legally override the abstract method(s) of I.

Pour faire court, une interface fonctionnelle n'est rien d'autre qu'une interface avec une méthode abstraite.

Exemple simple :

Voici un exemple simple :

ICode.java

 package fr.dr.practice;

/**
 * Interface with just one abstract method.
 */
public interface ICode {
    String generate(int codeNumber);
}
Main.java

package fr.dr.practice;

/**
 * Created with IntelliJ IDEA.
 */
public class Main {

    public static String generateTmpCode(int newCode) {
        ICode code = new ICode() {
            @Override
            public String generate(int codeNumber) {
                return "MAIN_" + codeNumber + Math.random();
            }
        };
        return code.generate(newCode);
    }

    public static String generateTmpCodeWithLambda(int newCode) {
        ICode icode = codeNumber -> "MAIN_" + codeNumber + Math.random();
        return icode.generate(newCode);
    }

    public static void main(String[] args) {
        System.out.println(Main.generateTmpCode(12));
        System.out.println(Main.generateTmpCodeWithLambda(12));

    }
}

Un peu plus dur ...

La JSR nous dit que dans certains cas, on peut définir plusieurs méthodes qui représente une seule méthode :

In some cases, this "single" method may take the form of multiple abstract methods with override-equivalent signatures (8.4.2) inherited from superinterfaces; in this case, the inherited methods logically represent a single method.

Nous pouvons donc faire le cas suivant car equals() est public dans la classe Object :

public interface ICode {

    String generate(int codeNumber);
    boolean equals(Object obj);
}

Cependant, il n'est pas possible d'utiliser la méthode clone() (protected Object clone() throws CloneNotSupportedException {) car elle n'est pas public dans la classe Object :

public interface ICode {

    String generate(int codeNumber);
    Object clone();
   
}

Function descriptor 

La JSR 335 ajoute aussi le concept de Functional descriptor.
Voici un exemple de la JSR pour comprendre cette notion :



interface X { void m() throws IOException; }
interface Y { void m() throws EOFException; }
interface Z { void m() throws ClassNotFoundException; }
interface XY extends X, Y {}
interface XYZ extends X, Y, Z {}

// XY has descriptor ()->void throws EOFException
// XYZ has descriptor ()->void (throws nothing)

Conclusion

Les interfaces fonctionnelles vont permettre d'utiliser les lambda et d'autres JAVA 8 features.
 Il existe déjà des interfaces fonctionnelles dans le package java.util (e.g java.util.Comparator ). Java 8 a aussi un nouveau package : java.util.functions qui définit de nouvelles interfaces fonctionnelles. Si vous voulez des exemples dessus, vous pouvez consulter cette excellent article : http://datumedge.blogspot.fr/2012/06/java-8-lambdas.html
Cet article a été l'occasion de découvrir une petite partie de JAVA 8.Si vous voyez des erreurs ou si vous avez des commentaires, n'hésitez pas ! Dans un prochain article, on étudiera les lambdas ...