T.() -> Unit
is an extension function type with receiver.
Besides ordinary functions, Kotlin supports extension functions. Such function differs from an ordinary one in that it has a receiver type specification. Here it's a generic T.
part.
The this
keyword inside an extension function corresponds to the receiver object (the one that is passed before the dot), so you can call its methods directly (referring to this
from parent scopes is still possible with qualifiers).
Function with
is a standard one, yes. It's current code:
/**
* Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
*
* For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#with).
*/
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
它是T
和R
的泛型函数,第一个参数"Receiver"类型为T
,第二个参数f
为扩展函数类型f
,扩展函数类型为T
,返回类型R
,而类型R
由with
返回.
For example, you can use it like this:
val threadInfoString = with (Thread.currentThread()) {
// isDaemon() & getPriority() are called with new property syntax for getters & setters
"${getName()}[isDaemon=$isDaemon,priority=$priority]"
}
See documentation for extension functions here:
kotlinlang.org/docs/reference/lambdas.html#extension-function-expressions
kotlinlang.org/docs/reference/scope-functions.html#with
kotlinlang.org/docs/reference/extensions.html
Added:
So the only valid f
would be any 0-argument function defined for T?
不是真的.在Kotlin function types and extension function types are unified中,以便它们可以互换使用.例如,我们可以在需要函数(String) -> Int
的地方传递String::length.
// 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
Or you can simply use function literal ({}
) as in the example with threadInfoString
, but it works only when the receiver type can be inferred from the context.