Kotlin
Les fonctions
Recherche…
Syntaxe
- fun Nom ( Params ) = ...
- Nom fun ( Params ) {...}
- fun Nom ( Params ): Type {...}
- fun < Type Argument > Name ( Params ): Type {...}
- inline fun Name ( Params ): tapez {...}
- { ArgName : ArgType -> ...}
- { ArgName -> ...}
- { ArgNames -> ...}
- {( ArgName : ArgType ): Type -> ...}
Paramètres
Paramètre | Détails |
---|---|
prénom | Nom de la fonction |
Params | Valeurs données à la fonction avec un nom et un type: Name : Type |
Type | Type de retour de la fonction |
Type Argument | Paramètre de type utilisé dans la programmation générique (pas nécessairement le type de retour) |
ArgName | Nom de la valeur donnée à la fonction |
ArgType | Spécificateur de type pour ArgName |
ArgNames | Liste de ArgName séparés par des virgules |
Fonctions prenant d'autres fonctions
Comme on le voit dans "Fonctions Lambda", les fonctions peuvent prendre d'autres fonctions en paramètre. Le "type de fonction" dont vous aurez besoin pour déclarer des fonctions prenant d'autres fonctions est le suivant:
# Takes no parameters and returns anything
() -> Any?
# Takes a string and an integer and returns ReturnType
(arg1: String, arg2: Int) -> ReturnType
Par exemple, vous pouvez utiliser le type le plus vague, () -> Any?
, pour déclarer une fonction qui exécute une fonction lambda deux fois:
fun twice(x: () -> Any?) {
x(); x();
}
fun main() {
twice {
println("Foo")
} # => Foo
# => Foo
}
Fonctions Lambda
Les fonctions Lambda sont des fonctions anonymes qui sont généralement créées lors d'un appel de fonction pour agir en tant que paramètre de fonction. Ils sont déclarés par des expressions environnantes avec {accolades} - si des arguments sont nécessaires, ils sont mis avant une flèche ->
.
{ name: String ->
"Your name is $name" //This is returned
}
La dernière instruction dans une fonction lambda est automatiquement la valeur de retour.
Les types sont optionnels, si vous placez le lambda sur un emplacement où le compilateur peut en déduire les types.
Plusieurs arguments:
{ argumentOne:String, argumentTwo:String ->
"$argumentOne - $argumentTwo"
}
Si la fonction lambda ne nécessite qu'un seul argument, la liste des arguments peut être omise et l'argument unique peut être utilisé it
place.
{ "Your name is $it" }
Si le seul argument d'une fonction est une fonction lambda, les parenthèses peuvent être complètement omises de l'appel de fonction.
# These are identical
listOf(1, 2, 3, 4).map { it + 2 }
listOf(1, 2, 3, 4).map({ it + 2 })
Références de fonction
Nous pouvons référencer une fonction sans l'appeler en préfixant le nom de la fonction avec ::
. Cela peut ensuite être passé à une fonction qui accepte une autre fonction en tant que paramètre.
fun addTwo(x: Int) = x + 2
listOf(1, 2, 3, 4).map(::addTwo) # => [3, 4, 5, 6]
Les fonctions sans récepteur seront converties en (ParamTypeA, ParamTypeB, ...) -> ReturnType
où ParamTypeA
, ParamTypeB
... sont le type des paramètres de la fonction et `ReturnType1 est le type de la valeur de retour de la fonction.
fun foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
//...
}
println(::foo::class.java.genericInterfaces[0])
// kotlin.jvm.functions.Function3<Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo0, Foo1, Foo2) -> Bar
Fonctions avec un récepteur (que ce soit une fonction d'extension ou une fonction membre) a une syntaxe différente. Vous devez ajouter le nom de type du récepteur avant les deux points suivants:
class Foo
fun Foo.foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
//...
}
val ref = Foo::foo
println(ref::class.java.genericInterfaces[0])
// kotlin.jvm.functions.Function4<Foo, Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo, Foo0, Foo1, Foo2) -> Bar
// takes 4 parameters, with receiver as first and actual parameters following, in their order
// this function can't be called like an extension function, though
val ref = Foo::foo
Foo().ref(Foo0(), Foo1(), Foo2()) // compile error
class Bar {
fun bar()
}
print(Bar::bar) // works on member functions, too.
Cependant, lorsque le récepteur d'une fonction est un objet, le récepteur est omis de la liste de paramètres, car il s'agit et n'est qu'une instance de ce type.
object Foo
fun Foo.foo(p0: Foo0, p1: Foo1, p2: Foo2): Bar {
//...
}
val ref = Foo::foo
println(ref::class.java.genericInterfaces[0])
// kotlin.jvm.functions.Function3<Foo0, Foo1, Foo2, Bar>
// Human readable type: (Foo0, Foo1, Foo2) -> Bar
// takes 3 parameters, receiver not needed
object Bar {
fun bar()
}
print(Bar::bar) // works on member functions, too.
Depuis kotlin 1.1, la référence de fonction peut également être liée à une variable, appelée alors référence de fonction bornée .
fun makeList(last: String?): List<String> {
val list = mutableListOf("a", "b", "c")
last?.let(list::add)
return list
}
Notez que cet exemple est donné uniquement pour montrer comment fonctionne la référence de fonction bornée. C'est une mauvaise pratique dans tous les autres sens.
Il y a cependant un cas particulier. Une fonction d'extension déclarée en tant que membre ne peut pas être référencée.
class Foo
class Bar {
fun Foo.foo() {}
val ref = Foo::foo // compile error
}
Les fonctions de base
Les fonctions sont déclarées à l'aide du mot-clé fun
, suivi d'un nom de fonction et de tous les paramètres. Vous pouvez également spécifier le type de retour d'une fonction, par défaut Unit
. Le corps de la fonction est entre accolades {}
. Si le type de retour est autre que Unit
, le corps doit émettre une déclaration de retour pour chaque branche de terminaison dans le corps.
fun sayMyName(name: String): String {
return "Your name is $name"
}
Une version abrégée du même:
fun sayMyName(name: String): String = "Your name is $name"
Et le type peut être omis car il peut être déduit:
fun sayMyName(name: String) = "Your name is $name"
Fonctions abrégées
Si une fonction ne contient qu'une seule expression, nous pouvons omettre les accolades et utiliser plutôt une équation comme une affectation de variable. Le résultat de l'expression est renvoyé automatiquement.
fun sayMyName(name: String): String = "Your name is $name"
Fonctions en ligne
Les fonctions peuvent être déclarées en ligne en utilisant le préfixe inline
, et dans ce cas elles agissent comme des macros dans C - plutôt que d'être appelées, elles sont remplacées par le code du corps de la fonction au moment de la compilation. Cela peut entraîner des avantages en termes de performances dans certaines circonstances, principalement lorsque les lambdas sont utilisés comme paramètres de fonction.
inline fun sayMyName(name: String) = "Your name is $name"
Une différence avec les macros C est que les fonctions en ligne ne peuvent pas accéder à la portée à partir de laquelle elles sont appelées:
inline fun sayMyName() = "Your name is $name"
fun main() {
val name = "Foo"
sayMyName() # => Unresolved reference: name
}
Fonctions opérateur
Kotlin nous permet de fournir des implémentations pour un ensemble prédéfini d'opérateurs avec une représentation symbolique fixe (comme +
ou *
) et une priorité fixe. Pour implémenter un opérateur, nous fournissons une fonction membre ou une fonction d'extension avec un nom fixe, pour le type correspondant. Les fonctions qui surchargent les opérateurs doivent être marquées avec le modificateur d' operator
:
data class IntListWrapper (val wrapped: List<Int>) {
operator fun get(position: Int): Int = wrapped[position]
}
val a = IntListWrapper(listOf(1, 2, 3))
a[1] // == 2
Vous trouverez plus de fonctions opérateur ici