class: center, middle background-image: url(img/background.png) #Java 8 - Les interfaces fonctionnelles Alexis Seigneurin -
[@aseigneurin](https://twitter.com/ASeigneurin)
-
[@ippontech](https://twitter.com/ippontech) --- class: center, middle # Interfaces fonctionnelles ? --- # Interface fonctionnelle * Interface avec une seule méthode abstraite * Méthodes par défaut = non-abstraites ```java public interface ExampleInterface { void doSomething(); } ``` --- # Annotation * @java.lang.FunctionalInterface ```java @FunctionalInterface public interface ExampleInterface { void doSomething(); default int methodWithDefaultImpl() { return 0; } } ``` --- # Vérification par le compilateur ```bash Unexpected @FunctionalInterface annotation com.seigneurin.ExampleInterface is not a functional interface multiple non-overriding abstract methods found in interface com.seigneurin.ExampleInterface ``` --- class: center, middle # Retour en arrière --- # Java 8 * Callback = classes anonymes ```java Button btn = new Button(); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); ``` --- # Exemple * On veut parser des noms : NameParser * On délègue la création du nom : Creator --- # Exemple ```java public class NameParser { public <T> T parse(String name, Creator<T> creator) { String[] tokens = name.split(" "); String firstName = tokens[0]; String lastName = tokens[1]; return creator.create(firstName, lastName); } } ``` --- # Exemple ```java public interface Creator<T> { T create(String firstName, String lastName); } public class Name { private String firstName; private String lastName; public Name(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } } ``` --- # Classe anonyme ```java NameParser parser = new NameParser(); Name res = parser.parse("Eric Clapton", new Creator<Name>() { @Override public Name create(String firstName, String lastName) { return new Name(firstName, lastName); } }); ``` --- class: center, middle # Java 8 --- # @FunctionalInterface * Annotation optionnelle ```java @FunctionalInterface public interface Creator<T> { T create(String firstName, String lastName); } ``` --- # Appel : une méthode... * Avec 2 paramètres de type String * Retour de type générique --- # Code appelé... * Méthode create() simulée par le compilateur --- # Référence vers un constructeur * Notation : "Classe::new" ```java NameParser parser = new NameParser(); Name res = parser.parse("Eric Clapton", Name::new); ``` --- # Référence vers une méthode statique * Notation : "Classe::méthode" ```java public class Factory { public static Name createName(String firstName, String lastName) { return new Name(firstName, lastName); } } ``` ```java NameParser parser = new NameParser(); Name res = parser.parse("Eric Clapton", Factory::createName); ``` --- # Référence vers une méthode d’instance * Notation : "instance::méthode" ```java public class Factory { public Name createName(String firstName, String lastName) { return new Name(firstName, lastName); } } ``` ```java Factory factory = new Factory(); NameParser parser = new NameParser(); Name res = parser.parse("Eric Clapton", factory::createName); ``` --- # Expression lambda ```java Name res = parser.parse("Eric Clapton", (s1, s2) -> new Name(s1, s2)); ``` ```java Name res = parser.parse("Eric Clapton", (s1, s2) -> Factory.createName(s1, s2)); ``` ```java Factory factory = new Factory(); Name res = parser.parse("Eric Clapton", (s1, s2) -> factory.createName(s1, s2)); ``` --- class: center, middle # Interfaces fonctionnelles du JDK --- # Consumer * java.util.function.Consumer<T> * Reçoit un paramètre * Ne retourne rien ```java void accept(T); ``` ```java Iterable
strings = Arrays.asList("a", "b", "c"); strings.forEach(System.out::println); ``` --- # Function * java.util.function.Function<T, R> * Reçoit un paramètre * Retourne une valeur ```java R apply(T); ``` ```java List
strings = Arrays.asList("b", "a", "c"); Comparator
comparator = Comparator.comparing(String::toLowerCase); strings.sort(comparator); ``` --- # Supplier * java.util.function.Supplier<T> * Ne reçoit rien * Retourne une valeur ```java T get(); ``` ```java Random random = new Random(42); Optional
opt = Optional.empty(); int value = opt.orElseGet(random::nextInt); ``` --- # Predicate * java.util.function.Predicate * Reçoit un paramètre * Retourne un booléen ```java boolean test(T); ``` ```java List
strings = new ArrayList
() {{ add("ab"); add("bb"); add("cb"); }}; strings.removeIf(s -> s.contains("c")); ``` --- class: center, middle # Plusieurs méthodes ? --- # Java < 8 ```java public interface Operation<T> { T function(); void onSuccess(T res); void onError(Exception ex); } ``` ```java public <T> void doSomething(Operation<T> operation) { try { T res = operation.function(); operation.onSuccess(res); } catch (Exception ex) { operation.onError(ex); } } ``` --- # Appel très verbeux ```java doSomething(new Operation<Object>() { @Override public Object function() { return 42; } @Override public void onSuccess(Object res) { System.out.println(res); } @Override public void onError(Exception ex) { System.err.println("Error: " + ex.getMessage()); } }); ``` --- # Java 8 * Stratégie = découper l'interface ```java public <T> void doSomething(Supplier<T> function, Consumer<T> onSuccess, Consumer<Exception> onError) { try { T res = function.get(); onSuccess.accept(res); } catch (Exception ex) { onError.accept(ex); } } ``` --- # Appel simplifié ```java doSomething( () -> 42, System.out::println, ex -> System.err.println("Error: " + ex.getMessage())); ``` --- class: center, middle background-image: url(img/background.png) # Questions ? Alexis Seigneurin -
[@aseigneurin](https://twitter.com/ASeigneurin) Code : [github.com/aseigneurin/pres-java8-bdxio](https://github.com/aseigneurin/pres-java8-bdxio) Slides : [aseigneurin.github.io/pres-java8-bdxio](/pres-java8-bdxio)