Anonymat et lambda
Introduction
Jusqu’à présent, les méthodes Java que nous avons développées ne prenaient en paramètres que des variables. Ce chapitre met un pied dans la programmation dite "fonctionnelle" en montrant comment passer également des "traitements" en paramètres.
Oui, mais pour quoi faire ?
Cela sert principalement à réduire votre code au prix cependant d’un petit apprentissage sur ces nouvelles syntaxes que nous allons découvrir.
Ce chapitre est divisé en deux parties. La première présente les classes anonymes qui furent une première façon concise de passer des traitements en paramètres. La seconde partie présente les expressions lambda, proposées depuis Java 8 et qui simplifient encore plus le code.
Les classes anonymes
1. D’une pierre deux coups
La classe anonyme est une classe déclarée et instanciée en même temps.
Elle réalise soit l’implémentation d’une interface connue soit l’extension d’une classe existante. Elle ne peut implémenter qu’une interface ou n’étendre qu’une seule classe à la fois.
La classe anonyme est une classe imbriquée (voir chapitre Création de classes), mais sans nom. Son instance est associée à celle de la classe qui la contient.
Elle n’est utile que si elle n’est "codée" qu’une seule fois. Si la fonctionnalité qu’elle supporte est demandée à plusieurs endroits de votre code alors il est préférable d’écrire une classe "nommée" comme nous l’avons fait jusqu’à présent. Cela évitera de la duplication de code.
2. Syntaxe particulière
Une classe anonyme est une expression et sa déclaration / instanciation se fait comme un appel de constructeur.
Syntaxe de déclaration
new <nom de la classe à étendre ou de l'interface à implémenter>()
{
// corps de la classe anonyme
};
L’opérateur new débute l’expression suivie soit d’un nom de classe à étendre, soit d’un nom d’interface à implémenter. Bien sûr, la classe ou l’interface en question doivent être connues. Les parenthèses qui suivent pourront contenir d’éventuels paramètres dans le cas d’une extension de classe. Rappelons qu’une interface n’a pas de constructeur. Ensuite arrive le corps de la classe qui peut contenir des méthodes et des données. Enfin, comme la classe anonyme est une expression, la séquence se termine par un point-virgule (;).
Exemple
Animal chien = new Animal(){
@Override
public String Crier() {
return "Ouaf Ouaf";
...
Les expressions lambda
1. Le concept
Nous venons de voir l’utilisation des classes anonymes pour coder "rapidement" des comportements. Cet outil apparu avec la version 1.1 de Java est tout de même un peu lourd à utiliser… Dix-sept ans plus tard, en 2014, Java 8 arrive avec ses expressions lambda présentées comme nouveauté majeure. Nouveauté majeure dans la Java sphère, car les développeurs C# composaient déjà avec les expressions lambda depuis 2007 avec cependant quelques différences.
Avec les expressions lambda, on passe de la déclaration/instanciation de la classe anonyme à celle de la fonction anonyme. On gagne encore en concision avec un code facile à écrire, à lire et à maintenir.
2. Les interfaces « fonctionnelles » comme modèles
Prenons un exemple d’implémentation d’interface par une classe anonyme et voyons comment les expressions lambda vont nous aider à rendre son code plus digeste…
Tout d’abord, prenons une interface contenant une seule méthode abstraite :
public interface IMath {
int Calculer(int i, int j);
}
Maintenant, créons autour de cette interface une classe anonyme avec, dans la foulée, son utilisation telle que nous l’avons vue dans la première partie de ce chapitre.
public void Demo1(int a, int b){
// Façon "classe anonyme"
IMath addition_classe_anonyme = new IMath(){
@Override
public int Calculer(int i, int j){
return i+j;
}
};
System.out.println(addition_classe_anonyme.Calculer(a,b));
}
Et voici le code équivalent façon "expression lambda" :
public void Demo1(int a, int b){
// Façon "expression lambda"
IMath addition_expression_lambda = (i,j)->i+j;
System.out.println(addition_expression_lambda.Calculer(a,b));
}
Comment est réalisé ce raccourci syntaxique qui nous simplifie bien les choses ? Reprenons élément par élément...