- Ils peuvent être nommés par des variables.
Oui, clairement :
Runnable r = () -> System.out.println("Hello");
Runnable r2 = System.out::println;
J'ai des fonctions / références de méthodes, et je peux avoir des variables nommées qui s'y réfèrent.
AMBIGUITÉ :
Ces variables pourraient également pointer sur des objets réels à la place :
r = new Runnable() {
public void run() {
System.out.println("Goodbye!");
}
};
Contrairement à l'exemple de la syntaxe de la fonction, l'exemple ci-dessus signifie que r
c'est vraiment pointer un objet défini avec des caractéristiques de type objet définies. Il existe un objet réel en mémoire et la spécification java lang le garantit.
Mais cela n'a pas d'importance. Dans un langage comme, disons, javascript ou python, je peux assigner n'importe quoi à une variable (les variables ne sont pas typées dans ces langages). Cela ne rend pas toutes les variables booléennes simplement parce que je peux assigner true
y false
à n'importe quelle variable.
De même, en Java, pour invoquer la fonction, par exemple pour imprimer Hello
donné : Runnable r = () -> System.out.println("Hello");
Je devrais écrire r.run()
et non r()
.
C'est un débat sur la syntaxe, ce n'est pas quelque chose de fondamental. En python, r()
prendra la variable r
Le logiciel de gestion de l'interface utilisateur, le déréférence (suit le pointeur), essaie d'interpréter ce qu'il trouve comme une fonction, et l'exécute, sans passer d'arguments. S'il n'est pas possible de l'interpréter comme une fonction, une erreur se produit.
Java n'est pas différent. r.run()
prendra la variable r
Le programme d'exécution, lui, le déréférence (suit le pointeur), essaie d'interpréter ce qu'il y trouve comme une fonction de type Runnable, et l'exécute, sans passer d'arguments. Si ce qu'il trouve n'est pas un Runnable (par exemple, il s'agit de null
), une erreur se produit.
Vous voyez ? c'est identique. Essayer de définir les choses en fonction de la manière dont d'autres langues font les choses conduirait à tort à dire que ce qui précède est en quelque sorte du "sucre syntaxique" qui "ne compte pas", ce qui est une conclusion erronée.
- Ils peuvent être transmis comme arguments aux procédures.
Oui, sans ambiguïté.
public void runTwice(Runnable r) {
r.run();
r.run();
}
Runnable r = () -> System.out.println("Hello");
runTwice(r);
runTwice(System.out::println);
runTwice(() -> System.out.println("Goodbye!"));
Je transmets ces fonctions à Java.
- Ils peuvent être renvoyés en tant que résultats de procédures.
Oui, sans ambiguïté :
public Runnable printMeTwice(String text) {
return () -> {
System.out.println(text);
System.out.println(text);
};
}
Runnable r = printMeTwice();
r.run();
- Ils peuvent être inclus dans des structures de données
Oui, sans ambiguïté :
class Animal {
String name;
Function<Food, Excrement> eat;
}
Animal animal = new Animal();
animal.eat = food -> return food.extractNutrients();
En cas d'ambiguïté.
En utilisant la formulation spécifique telle que vous l'avez collée, il n'y a aucune ambiguïté, ce qui est assez intéressant, étant donné que cette question a déjà reçu des réponses qui ont soit mal compris, soit utilisé des interprétations particulièrement bizarres de ces mots.
L'une des bizarreries de Java par rapport à la plupart des autres langages est que, dans la plupart des langages, si une variable r
contient une fonction, pour faire le travail de "déréférencer le pointeur et d'exécuter la fonction que vous trouvez lorsque vous le faites", vous écririez r()
. En Java, on ne fait pas cela ; on fait plutôt r.run()
ou r.apply(t)
en Java, les fonctions ont des types nommés, ce qui n'est pas le cas dans la plupart des langages. Par exemple, en Java, je peux avoir le concept d'une "opération de calculatrice sur des nombres entiers uniquement" :
IntCalcOp plusButton = (a, b) -> a + b;
et je peux avoir le concept d'une "fonction de comparaison de nombres entiers" :
IntComparator highestIsEarlier = (a, b) -> b - a;
et ces deux choses sont fondamentalement différentes. Je ne peux pas passer une variable de type IntCalcOp
à une méthode qui nécessite un IntComparator, même si les signatures sont entièrement identiques sur le plan fonctionnel - prennent tous deux 2 ints et renvoient un int.
Notez qu'il ne s'agit pas d'une situation intrinsèquement inférieure ; en fait, elle est probablement intrinsèquement supérieure. Il s'agit d'une différence d'opinion dans la conception du langage. Pour montrer les avantages du typage nominal et de l'absence totale de conversion implicite, voici deux définitions d'objets très simples qui sont fonctionnellement identiques :
interface Camera {
void shoot(Person p);
}
interface Gun {
void shoot(Person p);
}
Dans certains langages comme python et javascript, si je vous donne un pistolet et que vous attendez une caméra, vous tuerez quelqu'un. En Java, cela ne peut pas arriver.
Le fait de dire "mais c'est du sucre de syntaxe" ne change rien aux 4 extraits ci-dessus qui montrent clairement que Les fonctions de Java sont des éléments de premier ordre, conformément à la définition de la structure et de l'interprétation des programmes d'ordinateur. .
Je ne pense pas que ce livre ait une petite *
avec une note de bas de page qui précise "Le sucre syntaxique ne compte pas". Si vous souhaitez opérer avec cette mise en garde, il nous faut d'abord définir ce que signifie le sucre syntaxique.
Par exemple, la spécification du langage Java ne prévoit pas dire que ceux-ci sont transformés en littéraux anonymes de classe intérieure. Les implémentations ne le font même plus (d'autres réponses le mentionnent et sont incorrectes à cet égard).
Un compilateur C peut fonctionnent en émettant d'abord un code assembleur, puis en le faisant passer par un assembleur pour produire un exécutable. Cela signifie-t-il que tout le code C n'est que du "sucre syntaxique" ? Si c'est le cas, le C n'a même pas de boucles.
Ce type de raisonnement est intéressant, mais pour déterminer ce qu'un langage peut faire, je pense qu'il est complètement inutile. Essentiellement, tous les langages de programmation sont à 100 % du sucre syntaxique si l'on creuse suffisamment.