Kotlin
Funktionen
Suche…
Syntax
- Spaß Name ( Params ) = ...
- lustiger Name ( Params ) {...}
- Spaß Name ( Params ): Typ {...}
- Spaß <Typ Argument> Name (Param): Typ {...}
- Inline - Spaß - Name (Param): Typ {...}
- { ArgName : ArgType -> ...}
- { ArgName -> ...}
- { ArgNames -> ...}
- {( ArgName : ArgType ): Typ -> ...}
Parameter
Parameter | Einzelheiten |
---|---|
Name | Name der Funktion |
Params | Werte, die der Funktion mit einem Namen und Typ übergeben werden: Name : Type |
Art | Rückgabetyp der Funktion |
Geben Sie Argument ein | Typparameter, der in der generischen Programmierung verwendet wird (nicht unbedingt Rückgabetyp) |
ArgName | Name des Werts, der der Funktion gegeben wurde |
ArgType | Typbezeichner für ArgName |
ArgNames | Liste der durch Kommas getrennten ArgName |
Funktionen unter anderen Funktionen
Wie in "Lambda-Funktionen" gezeigt, können Funktionen andere Funktionen als Parameter annehmen. Der "Funktionstyp", den Sie zum Deklarieren von Funktionen benötigen, die andere Funktionen benötigen, lautet wie folgt:
# Takes no parameters and returns anything
() -> Any?
# Takes a string and an integer and returns ReturnType
(arg1: String, arg2: Int) -> ReturnType
Zum Beispiel könnten Sie den vagen Typ verwenden, () -> Any?
, um eine Funktion zu deklarieren, die eine Lambda-Funktion zweimal ausführt:
fun twice(x: () -> Any?) {
x(); x();
}
fun main() {
twice {
println("Foo")
} # => Foo
# => Foo
}
Lambda-Funktionen
Lambda-Funktionen sind anonyme Funktionen, die normalerweise während eines Funktionsaufrufs als Funktionsparameter erstellt werden. Sie werden durch umgebende Ausdrücke mit {geschweiften Klammern} deklariert. Wenn Argumente benötigt werden, werden diese vor einem Pfeil ->
.
{ name: String ->
"Your name is $name" //This is returned
}
Die letzte Anweisung innerhalb einer Lambda-Funktion ist automatisch der Rückgabewert.
Die Typen sind optional, wenn Sie das Lambda an einer Stelle ablegen, an der der Compiler auf die Typen schließen kann.
Mehrere Argumente:
{ argumentOne:String, argumentTwo:String ->
"$argumentOne - $argumentTwo"
}
Wenn die Lambda - Funktion ein Argument nur braucht, dann kann die Argumentliste weggelassen werden , und das einzige Argument zu verwenden bezeichnet it
stattdessen.
{ "Your name is $it" }
Wenn das einzige Argument einer Funktion eine Lambda-Funktion ist, können Klammern vollständig vom Funktionsaufruf weggelassen werden.
# These are identical
listOf(1, 2, 3, 4).map { it + 2 }
listOf(1, 2, 3, 4).map({ it + 2 })
Funktionsreferenzen
Wir können auf eine Funktion verweisen, ohne sie tatsächlich aufzurufen, indem Sie den Namen der Funktion mit ::
. Diese kann dann an eine Funktion übergeben werden, die eine andere Funktion als Parameter akzeptiert.
fun addTwo(x: Int) = x + 2
listOf(1, 2, 3, 4).map(::addTwo) # => [3, 4, 5, 6]
Funktionen ohne Empfänger werden in (ParamTypeA, ParamTypeB, ...) -> ReturnType
ParamTypeA
, wobei ParamTypeA
, ParamTypeB
... der Typ der Funktionsparameter sind und `ReturnType1 der Typ des Funktionsrückgabewerts.
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
Funktionen mit einem Empfänger (sei es eine Erweiterungsfunktion oder eine Memberfunktion) haben eine andere Syntax. Sie müssen den Typnamen des Empfängers vor dem Doppelpunkt eingeben:
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.
Wenn der Empfänger einer Funktion jedoch ein Objekt ist, wird der Empfänger nicht in der Parameterliste aufgeführt, da dies nur eine Instanz eines solchen Typs ist.
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.
Seit kotlin 1.1 kann die Funktionsreferenz auch auf eine Variable begrenzt werden, die dann als begrenzte Funktionsreferenz bezeichnet wird .
fun makeList(last: String?): List<String> {
val list = mutableListOf("a", "b", "c")
last?.let(list::add)
return list
}
Beachten Sie, dass dieses Beispiel nur dazu dient, zu zeigen, wie die Funktionsreferenz begrenzter Funktionen funktioniert. Es ist schlechte Praxis in allen anderen Sinnen.
Es gibt jedoch einen Sonderfall. Eine als Member deklarierte Erweiterungsfunktion kann nicht referenziert werden.
class Foo
class Bar {
fun Foo.foo() {}
val ref = Foo::foo // compile error
}
Basisfunktionen
Funktionen werden mit dem Schlüsselwort fun
deklariert, gefolgt von einem Funktionsnamen und beliebigen Parametern. Sie können auch den Rückgabetyp einer Funktion angeben, der standardmäßig auf Unit
. Der Hauptteil der Funktion ist in geschweifte Klammern {}
. Wenn der Rückgabetyp nicht Unit
, muss der Hauptteil für jede abschließende Verzweigung innerhalb des Hauptteils eine Rückgabeanweisung ausgeben.
fun sayMyName(name: String): String {
return "Your name is $name"
}
Eine Kurzfassung des gleichen:
fun sayMyName(name: String): String = "Your name is $name"
Und der Typ kann weggelassen werden, da darauf geschlossen werden kann:
fun sayMyName(name: String) = "Your name is $name"
Abkürzungsfunktionen
Wenn eine Funktion nur einen Ausdruck enthält, können wir die geschweiften Klammern weglassen und stattdessen ein Gleiches wie eine variable Zuweisung verwenden. Das Ergebnis des Ausdrucks wird automatisch zurückgegeben.
fun sayMyName(name: String): String = "Your name is $name"
Inline-Funktionen
Funktionen können mithilfe des inline
Präfixes inline deklariert werden. In diesem Fall verhalten sie sich wie C-Makros. Sie werden nicht aufgerufen, sondern werden beim Kompilieren durch den Bodycode der Funktion ersetzt. Dies kann unter Umständen zu Leistungsvorteilen führen, vor allem wenn Lambdas als Funktionsparameter verwendet werden.
inline fun sayMyName(name: String) = "Your name is $name"
Ein Unterschied zu C-Makros besteht darin, dass Inline-Funktionen nicht auf den Gültigkeitsbereich zugreifen können, aus dem sie aufgerufen werden:
inline fun sayMyName() = "Your name is $name"
fun main() {
val name = "Foo"
sayMyName() # => Unresolved reference: name
}
Bedienfunktionen
Kotlin ermöglicht es uns, Implementierungen für eine vordefinierte Gruppe von Operatoren mit fester symbolischer Darstellung (wie +
oder *
) und fester Priorität bereitzustellen. Um einen Operator zu implementieren, stellen wir eine Member-Funktion oder eine Erweiterungsfunktion mit festem Namen für den entsprechenden Typ bereit. Funktionen, die Überladungsoperatoren mit dem operator
Modifizierer kennzeichnen müssen:
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
Weitere Bedienfunktionen finden Sie hier