Les FAQs Java :
FAQ JAVA FAQ Java EE FAQ Java ME FAQ Java XML FAQ JavaFX FAQ Java GUI FAQ Struts FAQ JSF FAQ JDBC JDO FAQ Hibernate FAQ Spring FAQ Eclipse FAQ NetBeans FAQ JCreator FAQ Maven 2

FAQ JavaFXConsultez toutes les FAQ

Nombre d'auteurs : 4, nombre de questions : 86, dernière mise à jour : 2 juillet 2013 

 
OuvrirSommaireLangageLes FonctionsFonctions Avancées

Pour JavaFX, une signature de fonction est un type comme un autre. Il est donc possible de définir une variable comme étant une référence sur une fonction et appeler ainsi cette fonction quand on appelle cette variable.

Pour ce faire, il faut déclarer la variable suivie de deux points (:) , puis du mot-clé function puis de la liste des arguments de la fonction entre parenthèse puis de deux-points (:) et de son type de retour.

 
Sélectionnez

var bonjour: function():Void;

Ici, bonjour est une référence vers une fonction qui ne prend pas d'argument et ne retourne rien.
Par défaut, bonjour est initialisé à null. Si nous appellons :

 
Sélectionnez

bonjour() ;

Rien ne se passe.

De plus si nous imprimons la valeur de bonjour en faisant :

 
Sélectionnez

println(bonjour) ;

Nous obtenons :

 
Sélectionnez

null

Nous pouvons cependant lui affecter une valeur.
Définissons par exemple la fonction suivante :

 
Sélectionnez


function direBonjour() {
    println("Salut le monde !");
}
 

Si nous faisons :

 
Sélectionnez

var bonjour: function():Void;
function direBonjour() {
    println("Salut le monde !");
}
bonjour = direBonjour;
bonjour();

Notre programme va afficher le message Salut le monde !.
Si nous imprimons la valeur de bonjour, nous obtiendrons quelques chose de similaire à :

 
Sélectionnez

monScript$1@1506dc4

qui est la valeur de la référence sur la fonction que nous utilisons.

Nous pouvons bien sur affecter d'autres valeurs à notre variable en cours d'exécution, ainsi le code suivant :

 
Sélectionnez

println(bonjour);
bonjour();
println("=============================");
function test1():Void {
    println("Hello world!");
}
bonjour = test1;
println(bonjour);
bonjour();
println("=============================");
function test2():Void {
    println("Salut le monde !");
}
bonjour = test2;
println(bonjour);
bonjour(); 

Produira quelques chose de similaire à :

 
Sélectionnez


=============================
null
=============================
monScript$1@1506dc4
Hello world!
=============================
monScript$2@a761fe
Salut le monde ! 

Car

  1. La variable est initialisée à null rien ne s'affiche.
  2. La variable prend la référence de la fonction test1() et affiche Hello world!.
  3. La variable prend la référence de la fonction test2() et affiche Salut le monde !.

Si nous essayons d'affecter des fonctions dont la signature ne correspond pas à la définition de notre variable, des erreurs seront générées par le compilateur ou l'IDE.
Ainsi le code suivant ne compilera pas :

 
Sélectionnez


function test3(x:Number):Void {
    println("{x}");
}
bonjour = test3;
println(bonjour);
bonjour ();
function test4():Number {
    return 0;
}
bonjour = test4;
println(bonjour);
bonjour ();

En effet, aucune des deux fonctions ne correspond à la signature utilisée pour la définition de bonjour.

Il est bien sûr possible de définir des signatures de référence sur des fonctions prenant en paramètres plusieurs arguments ou ayant des types de retour. Ainsi le code suivant est tout à fait valide :

 
Sélectionnez

 
var add:function(x:Number, y:Number):Number;
function addNumber(x:Number, y:Number):Number {
    return x+y;
}
add=addNumber;
println(add(3, 4));

Une fois executé ce code affichera la valeur 7.0.

On remarquera également qu'il est impossible d'appeler la variable add sans argument ou avec le mauvais nombre d'arguments entre les parenthèses car cela ne correspond pas à la signature utilisée. Ainsi, le code suivant ne compilera pas :

 
Sélectionnez


println(add());
println(add(1));
println(add(1, 2, 3));
 

Avant d'utiliser des références de fonction, vous devez cependant prendre garde à ce que vos références soient correctement initialisées.
Ainsi :

 
Sélectionnez

var add:function(x:Number, y:Number):Number;
println(add(3, 4));
println(add);
println("=============================");
function addNumber(x:Number, y:Number):Number {
    return x+y;
}
add=addNumber;
println(add(3, 4));
println(add);

Produira un résultat similaire à :

 
Sélectionnez

0.0
null
=============================
7.0
monScript$1@a761fe 

En effet,

  1. La variable add est non-initialisée et donc à null. La valeur retournée est 0.0 qui est la valeur par défaut pour Number.
  2. La variable add est initialisée avec notre fonction et retourne la valeur correcte.

Il faudra donc manier ce concept avec précautions.

Créé le 27 janvier 2009  par bouye

Il est possible de faire un callback en créant une variable qui est une référence de fonction à l'intérieur d'une classe.
Par exemple :

 
Sélectionnez

public class Toto {
    public var onXXXChange:function():Void;
 
    public function faireQuelqueChose():Void {
        onXXXChange();
    }
}

Dans ce cas, la variable onXXXChange est définie comme étant une référence sur une fonction qui ne prend pas d'argument et qui ne retourne rien.
Nous pouvons donc appeler cette variable comme s'il s'agissait d'une fonction depuis le code de la classe et il est également possible d'accéder directement à cette variable depuis l'extérieur de la classe.
Par défaut la variable est initialisée à null et le code ne fait strictement rien.

Note : le nom de la variable importe peu et vous pouvez la nommer comme bon vous semble.

Si nous écrivons

 
Sélectionnez

var toto1 = Toto{
}
toto1.faireQuelqueChose();

A l'exécution, il ne se passe rien.

Lorsque nous implémentons notre classe, il est possible de redéfinir la variable onXXXChange comme n'importe quelle autre variable publique qui ne soit pas marquée public-read.

Par exemple :

 
Sélectionnez

var toto2 = Toto {
    onXXXChange: function():Void {
        println("onXXXChange");
    }
}
toto2.faireQuelqueChose();

À l'execution, le texte onXXXChange s'affichera.

Vous pouvez remarquer que la gestion des évènements claviers et souris dans l'API SceneGraph fonctionne exactement de la même manière.
Vous serez donc ammener à surcharger les valeurs par défaut des variables onMouseClicked ou onKeyPressed (par exemple) pour gérer les événements dans la classe javafx.stage.Node et ses classes filles.

Vous pouvez sans problème définir des variables avec des signatures de fonction qui prennent plusieurs arguments ou qui ont même un type de retour.
Dans tous les cas, vous devrez faire attention à ce que vos variables soient correctement définies :

 
Sélectionnez

public class Toto {
    public var onXXXChange:function():Void;
 
    public var onYYYChange:function(x:Number, y:Number):Number;
 
    public function faireQuelqueChose1():Void {
        onXXXChange();
    }
 
    public function faireQuelqueChose2(x:Number, y:Number):Number {
       return onYYYChange(x, y);
    }
}
 
var toto1 = Toto{
}
var toto2 = Toto {
    onXXXChange: function():Void {
        println("onXXXChange");
    }
    onYYYChange: function(x:Number, y:Number):Number {
        println("{x}, {y}");
        return x+y;
    }
}
println("=======================");
toto1.faireQuelqueChose1();
println(toto1.onYYYChange);
println(toto1.onYYYChange(1, 2));
println(toto1.faireQuelqueChose2(1, 2));
println("=======================");
toto2.faireQuelqueChose1();
println(toto2.onYYYChange);
println(toto2.onYYYChange(1, 2));
println(toto2.faireQuelqueChose2(1, 2));

Le résultat de l'exécution d'un tel code sera :

 
Sélectionnez

=======================
null
0.0
0.0
=======================
onXXXChange
monScript$2@1be0f0a
1.0, 2.0
3.0
1.0, 2.0
3.0
Dans le cas de toto1 :
  1. L'appel à la methode faireQuelqueChose1() n'imprime rien car onXXXChange n'est pas défini.
  2. L'impression directe de onYYYChange affiche null car onYYYChange n'est pas défini.
  3. L'acces direct direct à onYYYChange retourne retourne 0.0 qui est la valeur des Number (le type de retour dans la signature de la fonction) par défaut.
  4. L'appel à la méthode faireQuelqueChose2() retourne 0.0 qui est la valeur des Number par défaut.
Dans le cas de toto2 :
  1. L'appel à la méthode faireQuelqueChose1() imprime bien onXXXChange puisque la fonction que nous avons définie est appelée.
  2. L'impression directe de onYYYChange affiche la référence de la fonction que nous avons defini.
  3. L'accès direct à onYYYChange imprime bien les valeurs de x et y et retourne le résultat correct de la fonction que nous avons défini.
  4. L'appel à la méthode faireQuelqueChose2() imprime bien les valeurs de x et y et retourne le résultat correct de la fonction que nous avons défini.

Une fois de plus, il faudra donc manier ce concept avec précautions.

Créé le 27 janvier 2009  par bouye
Les codes sources sont, sauf mention spéciale, libres de droits, et vous pouvez les utiliser à votre convenance. Pour le reste, ce document constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright © 2009 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction, ne peux en être faite sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.