quand utiliser une fonction inline dans Kotlin?
Je sais qu'une fonction inline va peut-être améliorer les performances & cause le code généré pour grandir, mais je ne suis pas sûr que lorsqu'il est correctement l'utiliser.
lock(l) { foo() }
Au lieu de créer un objet de fonction pour le paramètre et la génération d'un appel, le compilateur pourrait émettre le code suivant. (Source)
l.lock()
try {
foo()
}
finally {
l.unlock()
}
mais j'ai trouvé qu'il n'y a pas de fonction d'objet créé par kotlin, pour un non-fonction inline. pourquoi?
/**non-inline function**/
fun lock(lock: Lock, block: () -> Unit) {
lock.lock();
try {
block();
} finally {
lock.unlock();
}
}
- Il existe deux principaux cas d'utilisation pour cela, on est avec certains types de fonctions supérieures, et l'autre est réifiée des paramètres de type. La documentation des fonctions inline couvre-ci: kotlinlang.org/docs/reference/inline-functions.html
- merci, monsieur. mais je ne comprends pas que : "au Lieu de créer un objet de fonction pour le paramètre et la génération d'un appel, le compilateur pourrait émettre le code suivant"
- je n'obtiens que l'exemple soit tbh.
Vous devez vous connecter pour publier un commentaire.
Disons que vous créez un ordre supérieur de la fonction qui prend un lambda de type
() -> Unit
(pas de paramètres, pas de valeur de retour), et l'exécute comme suit:Dans le langage Java, cela permettra de passer à quelque chose comme ceci (simplifié!):
Et quand vous l'appelez de Kotlin...
Sous le capot, une instance de
Function
seront créés ici, qui encapsule le code à l'intérieur de la lambda (encore une fois, c'est simplifié):Donc, fondamentalement, à l'appel de cette fonction, et en passant une lambda pourra toujours créer une instance d'un
Function
objet.D'autre part, si vous utilisez le
inline
mot-clé:Quand vous l'appelez comme ceci:
Pas
Function
instance sera créée, au lieu de cela, le code autour de l'invocation deblock
à l'intérieur de la fonction inline seront copiés sur le site d'appel, de sorte que vous obtiendrez quelque chose comme ceci dans le bytecode:Dans ce cas, pas de nouvelles instances sont créées.
noinline
etcrossinline
des mots - clés, voir la docs.Permettez-moi d'ajouter: "Quand ne pas utiliser
inline
":1) Si vous disposez d'une simple fonction qui n'acceptent pas d'autres fonctions comme un argument, il ne fait pas de sens pour inline eux. IntelliJ vous préviens:
2) Même si vous avez une fonction "avec des paramètres de types fonctionnels", vous risquez de rencontrer le compilateur vous dire que l'in-lining ne fonctionne pas. Considérons cet exemple:
Ce code ne compile pas avec l'erreur:
La raison en est que le compilateur n'est pas en mesure de l'inclure ce code. Si
operation
n'est pas encapsulée dans un objet (qui est implicite parinline
puisque vous ne voulez pas que cela), comment peut-il être affecté à une variable à tous? Dans ce cas, le compilateur suggère l'argumentnoinline
. Avoir uninline
fonction avec un seulnoinline
fonction n'a aucun sens, ne pas le faire. Cependant, s'il y a plusieurs paramètres de types fonctionnels, considérer l'in-lining certains d'entre eux, si nécessaire.Voici donc quelques règles suggérées:
noinline
pour le reste.reified
paramètres de type, qui vous obligent à utiliserinline
. Lire ici.Le plus important cas lorsque nous utilisons inline modificateur est lorsque nous définissons util-comme des fonctions avec des paramètres des fonctions. De la collecte ou du traitement de chaîne (comme
filter
,ma
p oujoinToString
) ou juste autonome les fonctions sont l'exemple parfait.C'est pourquoi inline modificateur est surtout une importante optimisation pour les développeurs de la bibliothèque. Ils doivent savoir comment ça fonctionne et quels sont ses améliorations et des coûts. Nous allons utiliser inline modificateur dans nos projets quand nous définissons notre propre util fonctions avec la fonction des paramètres de type.
Lorsque nous n'avons pas de fonction de type de paramètre, réifiée paramètre de type, et nous n'avons pas besoin de non-retour locale, puis nous avons le plus probable ne devriez pas utiliser inline modificateur. C'est pourquoi nous allons avoir un avertissement sur Android Studio ou l'IDÉE d'IntelliJ.
Il y a aussi le code de la taille du problème. Inline une grande fonction pourrait augmenter considérablement la taille du bytecode parce que c'est copié à tous les appels site. Dans de tels cas, vous pouvez restructurer la fonction et l'extrait de code pour des fonctions classiques.