T.() -> Unit
- тип функции расширения с приемником.
Помимо обычных функций, Kotlin поддерживает функции расширения. Такая функция отличается от обычной, поскольку она имеет спецификацию типа приемника. Здесь это общая часть T.
.
this
ключевое слово внутри функции расширения соответствует объекту приемника (тот, который передается перед точкой), так что вы можете вызвать его методы напрямую (со ссылкой на this
от родительских областей все еще возможно with qualifiers).
Функция with
является стандартной, да. Это текущий код:
/**
* Calls the specified function [f] with the given [receiver] as its receiver and returns its result.
*/
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
Так что это общая функция для T
и R
, с первым аргументом «приемник» типа T
и второй, f
удлинителя типа функции, которая простирается T
, тип R
возвращение в свою очередь, вернулся по with
.
Например, вы можете использовать его как это:
val threadInfoString = with (Thread.currentThread()) {
// isDaemon() & getPriority() are called with new property syntax for getters & setters
"${getName()}[isDaemon=$isDaemon,priority=$priority]"
}
смотрите документацию для функции расширения здесь:
kotlinlang.org/docs/reference/lambdas.html#extension-function-expressions
kotlinlang.org/docs/reference/extensions.html
Добавлено:
Таким образом, единственной допустимой f
будет любая функция 0-аргумента, определенная для T?
Не совсем. В Kotlin function types and extension function types are unified, так что они могут использоваться взаимозаменяемо. Например, мы можем передать String :: length, где ожидается функция (String) -> Int
.
// map() expects `(String) -> Int`
// argument has type `String.() -> Int`
strings.map(String::length)
типы, как Thread.() -> String
& (Thread) -> String
одинаковы с фоновой стороны - приемник, по сути, является первым аргументом.
Таким образом, любой из следующих функций подходят для Thread.() -> String
аргумента:
fun main(args: Array<String>) {
val f1 = fun Thread.(): String = name
val f2 = fun Thread.() = name
val f3: Thread.() -> String = { name }
val f4: (Thread) -> String = { it.name }
val f5 = { t: Thread -> t.name }
val f6: (Thread) -> String = Thread::getNameZ
val f7: Thread.() -> String = Thread::getNameZ
val f8 = Thread::getNameZ
}
fun Thread.getNameZ() = name
Или вы можете просто использовать function literal ({}
), как в примере с threadInfoString
, но он работает только тогда, когда тип приемника может быть выведен из контекста.
Благодарим вас за отличный ответ, я должен был сложить каждый fx сам, чтобы понять их. Интересно, что изучение основ Scala было проще: D Но, возможно, еще один вопрос: в чем разница между «Class1.() -> Class2' и« (Class1) -> Class2' – ssuukk
OK, я знаю - 'Class1.() -> Class2' принимает функцию и имеет 'this', а' (Class1) -> Class2' принимает лямбда и имеет 'it' – ssuukk
@ssuukk да, вы правы -' Class1.() -> Class2' имеет 'this' , а '(Class1) -> Class2' имеет' it'. Оба являются взаимозаменяемыми функциями. –