2015-10-17 5 views
13

Это стандартная функция Котлин (насколько я знаю)Что означает подпись функции Kotlin с T.()?

inline fun<T> with(t: T, body: T.() -> Unit) { t.body() } 

Но кто-то может написать в простом английском языке, что делает именно подпись означает? Это общая функция для T, с первым аргументом «t» типа T, а во-вторых, «тело» типа функции, принимающее функцию ???? и не возвращая ничего (Unit)

Я вижу это обозначение Something() -> Что-то используется довольно часто, то есть для Анко:.

inline fun Activity.coordinatorLayout(init: CoordinatorLayout.() -> Unit) = ankoView({ CoordinatorLayout(it) },init) 

, но я не думаю, что это было объяснено в любом месте, что (.) ...

ответ

15

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, но он работает только тогда, когда тип приемника может быть выведен из контекста.

+0

Благодарим вас за отличный ответ, я должен был сложить каждый fx сам, чтобы понять их. Интересно, что изучение основ Scala было проще: D Но, возможно, еще один вопрос: в чем разница между «Class1.() -> Class2' и« (Class1) -> Class2' – ssuukk

+0

OK, я знаю - 'Class1.() -> Class2' принимает функцию и имеет 'this', а' (Class1) -> Class2' принимает лямбда и имеет 'it' – ssuukk

+0

@ssuukk да, вы правы -' Class1.() -> Class2' имеет 'this' , а '(Class1) -> Class2' имеет' it'. Оба являются взаимозаменяемыми функциями. –

Смежные вопросы