Поиск…
Синтаксис
- fun Имя ( Params ) = ...
- fun Имя ( Params ) {...}
- fun Имя ( Params ): Введите {...}
- fun < Type Argument > Name ( Params ): Type {...}
- inline fun Имя ( Params ): Введите {...}
- { ArgName : ArgType -> ...}
- { ArgName -> ...}
- { ArgNames -> ...}
- {( ArgName : ArgType ): Тип -> ...}
параметры
параметр | подробности |
---|---|
название | Название функции |
Params | Значения, присвоенные функции с именем и типом: Name : Type |
Тип | Тип возвращаемой функции |
Тип Аргумент | Параметр типа, используемый в общем программировании (необязательно возвращаемый тип) |
ArgName | Название значения, заданного функции |
тип аргумента | Спецификатор типа для ArgName |
ArgNames | Список ArgName, разделенный запятыми |
Функции, выполняющие другие функции
Как видно из «Лямбда-функций», функции могут принимать другие функции в качестве параметра. «Тип функции», который вам потребуется для объявления функций, выполняющих другие функции, выглядит следующим образом:
# Takes no parameters and returns anything
() -> Any?
# Takes a string and an integer and returns ReturnType
(arg1: String, arg2: Int) -> ReturnType
Например, вы можете использовать нечеткий тип, () -> Any?
, чтобы объявить функцию, которая выполняет лямбда-функцию дважды:
fun twice(x: () -> Any?) {
x(); x();
}
fun main() {
twice {
println("Foo")
} # => Foo
# => Foo
}
Лямбда-функции
Лямбда-функции - это анонимные функции, которые обычно создаются во время вызова функции, чтобы действовать как параметр функции. Они объявляются окружающими выражениями с помощью {braces} - если нужны аргументы, они помещаются перед стрелкой ->
.
{ name: String ->
"Your name is $name" //This is returned
}
Последним утверждением внутри лямбда-функции является автоматически возвращаемое значение.
Тип необязателен, если вы помещаете лямбду в место, где компилятор может вывести типы.
Несколько аргументов:
{ argumentOne:String, argumentTwo:String ->
"$argumentOne - $argumentTwo"
}
Если функция лямбда нужен только один аргумент, то список аргументов может быть опущен , и единственный аргумент упоминаться , используя it
вместо этого.
{ "Your name is $it" }
Если единственным аргументом функции является лямбда-функция, то круглые скобки могут быть полностью исключены из вызова функции.
# These are identical
listOf(1, 2, 3, 4).map { it + 2 }
listOf(1, 2, 3, 4).map({ it + 2 })
Ссылки на функции
Мы можем ссылаться на функцию, не называя ее, префиксное имя функции с помощью ::
. Затем это можно передать функции, которая принимает какую-либо другую функцию в качестве параметра.
fun addTwo(x: Int) = x + 2
listOf(1, 2, 3, 4).map(::addTwo) # => [3, 4, 5, 6]
Функции без приемника будут преобразованы в (ParamTypeA, ParamTypeB, ...) -> ReturnType
где ParamTypeA
, ParamTypeB
... являются типом параметров функции, а `ReturnType1 - тип возвращаемого значения функции.
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
Функции с приемником (будь то функция расширения или функция-член) имеют другой синтаксис. Вы должны добавить имя типа приемника перед двойным двоеточием:
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.
Однако, когда приемник функции является объектом, приемник опускается из списка параметров, потому что это и есть только один экземпляр такого типа.
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.
Так как kotlin 1.1, ссылка на функцию также может быть ограничена переменной, которая затем называется ссылкой на ограниченную функцию .
fun makeList(last: String?): List<String> {
val list = mutableListOf("a", "b", "c")
last?.let(list::add)
return list
}
Обратите внимание, что этот пример приведен только для того, чтобы показать, как работает ограниченная ссылка на функцию. Это плохая практика во всех других смыслах.
Однако есть особый случай. Нельзя ссылаться на функцию расширения, объявленную как член.
class Foo
class Bar {
fun Foo.foo() {}
val ref = Foo::foo // compile error
}
Основные функции
Функции объявляются с использованием ключевого слова fun
, за которым следует имя функции и любые параметры. Вы также можете указать тип возврата функции, которая по умолчанию относится к Unit
. Тело функции заключено в фигурные скобки {}
. Если тип возврата отличается от Unit
, тело должно выдать оператор возврата для каждой завершающей ветви внутри тела.
fun sayMyName(name: String): String {
return "Your name is $name"
}
Сокращенная версия того же:
fun sayMyName(name: String): String = "Your name is $name"
И тип может быть опущен, так как можно сделать вывод:
fun sayMyName(name: String) = "Your name is $name"
Сокращенные функции
Если функция содержит только одно выражение, мы можем опустить скобки скобок и вместо этого использовать равные значения, как назначение переменной. Результат выражения возвращается автоматически.
fun sayMyName(name: String): String = "Your name is $name"
Встроенные функции
Функции могут быть объявлены inline с помощью inline
префикса, и в этом случае они действуют как макросы в C - вместо того, чтобы быть вызванными, они заменяются кодом тела функции во время компиляции. Это может привести к повышению производительности при некоторых обстоятельствах, главным образом там, где lambdas используются в качестве функциональных параметров.
inline fun sayMyName(name: String) = "Your name is $name"
Одно отличие от макросов C состоит в том, что встроенные функции не могут получить доступ к области, из которой они вызваны:
inline fun sayMyName() = "Your name is $name"
fun main() {
val name = "Foo"
sayMyName() # => Unresolved reference: name
}
Функции оператора
Kotlin позволяет нам предоставлять реализации для предопределенного набора операторов с фиксированным символическим представлением (например, +
или *
) и фиксированным приоритетом. Для реализации оператора мы предоставляем функцию-член или функцию расширения с фиксированным именем для соответствующего типа. Функции, которые перегружают операторы, должны быть отмечены модификатором 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
Дополнительные функции оператора можно найти в здесь