Je cherche un moyen de passer une méthode par référence. Je comprends que Java ne passe pas les méthodes comme paramètres, cependant, je voudrais obtenir une alternative.
On m'a dit que les interfaces sont l'alternative au passage de méthodes en tant que paramètres, mais je ne comprends pas comment une interface peut agir comme une méthode par référence. Si je comprends bien, une interface est simplement un ensemble abstrait de méthodes qui ne sont pas définies. Je ne veux pas envoyer une interface qui doit être définie à chaque fois car plusieurs méthodes différentes pourraient appeler la même méthode avec les mêmes paramètres.
Ce que je voudrais accomplir est quelque chose de similaire à ceci:
public void setAllComponents(Component[] myComponentArray, Method myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) { //recursive call if Container
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
} //end if node
myMethod(leaf);
} //end looping through components
}
invoquées telles que:
setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
Réponses:
Edit : à partir de Java 8, les expressions lambda sont une bonne solution comme l' ont souligné d' autres réponses . La réponse ci-dessous a été écrite pour Java 7 et versions antérieures ...
Jetez un œil au modèle de commande .
Edit: comme le souligne Pete Kirkham , il existe une autre façon de le faire en utilisant un visiteur . L'approche visiteur est un peu plus impliquée - vos nœuds doivent tous être attentifs aux visiteurs avec une
acceptVisitor()
méthode - mais si vous devez parcourir un graphique d'objet plus complexe, cela vaut la peine d'être examiné.la source
Dans Java 8, vous pouvez désormais transmettre une méthode plus facilement à l'aide d' expressions Lambda et de références de méthode. Tout d'abord, quelques informations: une interface fonctionnelle est une interface qui a une et une seule méthode abstraite, bien qu'elle puisse contenir un nombre illimité de méthodes par défaut (nouveau dans Java 8) et de méthodes statiques. Une expression lambda peut rapidement implémenter la méthode abstraite, sans toute la syntaxe inutile nécessaire si vous n'utilisez pas d'expression lambda.
Sans expressions lambda:
Avec des expressions lambda:
Voici un extrait du tutoriel Java sur les expressions Lambda :
Voici comment vous pouvez "passer une méthode" en utilisant une expression lambda:
La classe
C
peut être raccourcie encore un peu plus en utilisant des références de méthode comme ceci:la source
::
opérateur), peu importe ce qu'est A.a.changeThing(component)
peut être changé en n'importe quelle instruction ou bloc de code que vous voulez, tant qu'il renvoie void.Utilisez l'
java.lang.reflect.Method
objet et appelezinvoke
la source
Depuis Java 8, il existe une
Function<T, R>
interface ( docs ), qui a une méthodeVous pouvez l'utiliser pour passer des fonctions comme paramètres à d'autres fonctions. T est le type d'entrée de la fonction, R est le type de retour.
Dans votre exemple, vous devez passer une fonction qui prend le
Component
type en entrée et ne renvoie rien -Void
. Dans ce cas, ceFunction<T, R>
n'est pas le meilleur choix, car il n'y a pas de boîte automatique de type Void. L'interface que vous recherchez s'appelleConsumer<T>
( docs ) avec méthodeCela ressemblerait à ceci:
Et vous l'appeleriez en utilisant des références de méthode:
En supposant que vous avez défini les méthodes changeColor () et changeSize () dans la même classe.
Si votre méthode accepte plusieurs paramètres, vous pouvez utiliser
BiFunction<T, U, R>
- T et U étant des types de paramètres d'entrée et R étant un type de retour. Il y en a aussiBiConsumer<T, U>
(deux arguments, pas de type de retour). Malheureusement, pour 3 paramètres d'entrée et plus, vous devez créer vous-même une interface. Par exemple:la source
Définissez d'abord une interface avec la méthode que vous souhaitez passer en paramètre
Implémenter une classe avec la méthode
// Invoque comme ça
Cela vous permet de passer cmd en paramètre et d'appeler l'appel de méthode défini dans l'interface
la source
Bien que cela ne soit pas encore valable pour Java 7 et les versions antérieures , je pense que nous devons regarder vers l'avenir et au moins reconnaître les changements à venir dans les nouvelles versions telles que Java 8.
À savoir, cette nouvelle version apporte des lambdas et des références de méthode à Java (ainsi que de nouvelles API , qui sont une autre solution valide à ce problème. Bien qu'ils nécessitent toujours une interface, aucun nouvel objet n'est créé, et les fichiers de classe supplémentaires ne doivent pas polluer les répertoires de sortie en raison de différents prise en charge par la JVM.
Les deux versions (lambda et référence de méthode) nécessitent une interface disponible avec une seule méthode dont la signature est utilisée:
Les noms de méthodes n'auront plus d'importance à partir de maintenant. Lorsqu'un lambda est accepté, une référence de méthode l'est également. Par exemple, pour utiliser notre signature ici:
Ceci est juste une simple invocation d'interface, jusqu'à ce que le lambda 1 soit passé:
Cela produira:
Les références de méthode sont similaires. Donné:
et principal:
la sortie serait
real static method
. Les références de méthode peuvent être statiques, d'instance, non statiques avec des instances arbitraires et même des constructeurs . Pour le constructeur, quelque chose de semblableClassName::new
serait utilisé.1 Ceci n'est pas considéré comme un lambda par certains, car il a des effets secondaires. Il illustre cependant l'utilisation de celui-ci d'une manière plus simple à visualiser.
la source
La dernière fois que j'ai vérifié, Java n'est pas capable de faire nativement ce que vous voulez; vous devez utiliser des solutions de contournement pour contourner ces limitations. Pour moi, les interfaces SONT une alternative, mais pas une bonne alternative. Peut-être que celui qui vous a dit que cela signifiait quelque chose comme ceci:
Avec quoi vous invoqueriez alors:
la source
Si vous n'avez pas besoin de ces méthodes pour renvoyer quelque chose, vous pouvez leur faire renvoyer des objets Runnable.
Ensuite, utilisez-le comme:
la source
Je n'ai trouvé aucun exemple suffisamment explicite pour moi sur la façon d'utiliser
java.util.function.Function
une méthode simple comme fonction de paramètre. Voici un exemple simple:Fondamentalement, vous avez un
Foo
objet avec un constructeur par défaut. Unmethod
qui sera appelé comme paramètre duparametrisedMethod
qui est de typeFunction<String, Foo>
.Function<String, Foo>
signifie que la fonction prend unString
paramètre as et renvoie aFoo
.Foo::Method
correspond à un lambda commex -> Foo.method(x);
parametrisedMethod(Foo::method)
pourrait être considéré commex -> parametrisedMethod(Foo.method(x))
.apply("from a method")
essentiellement à faireparametrisedMethod(Foo.method("from a method"))
Qui retournera alors dans la sortie:
L'exemple devrait fonctionner tel quel, vous pouvez ensuite essayer des choses plus compliquées à partir des réponses ci-dessus avec différentes classes et interfaces.
la source
Java a un mécanisme pour passer le nom et l'appeler. Cela fait partie du mécanisme de réflexion. Votre fonction doit prendre un paramètre supplémentaire de la classe Method.
la source
Je ne suis pas un expert java mais je résous votre problème comme ceci:
Je définis le paramètre dans mon interface spéciale
Enfin, j'implémente la méthode getSearchText lors de l'appel de la méthode initialize .
la source
Utilisez le modèle Observer (parfois aussi appelé modèle Listener):
new ComponentDelegate()...
déclare un type anonyme implémentant l'interface.la source
Voici un exemple de base:
Production:
la source
Je n'ai trouvé aucune solution ici qui montre comment passer une méthode avec des paramètres liés à elle comme paramètre d'une méthode. Ci-dessous est un exemple de la façon dont vous pouvez passer une méthode avec des valeurs de paramètre déjà liées.
Un autre exemple montre comment passer une méthode qui retourne réellement quelque chose
la source
Exemple de solution avec réflexion, la méthode passée doit être publique
la source
J'apprécie les réponses ci-dessus mais j'ai pu obtenir le même comportement en utilisant la méthode ci-dessous; une idée empruntée aux rappels Javascript. Je suis ouvert à la correction mais jusqu'ici tout va bien (en production).
L'idée est d'utiliser le type de retour de la fonction dans la signature, ce qui signifie que le rendement doit être statique.
Vous trouverez ci-dessous une fonction qui exécute un processus avec un délai d'expiration.
la source