与T.()的Kotlin函数签名是什么意思?

时间:2015-10-17 19:20:07

标签: kotlin

这是标准的Kotlin功能(据我所知)

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

但是,任何人都可以用简单的英文写下签名的意思吗?它是T的通用函数,第一个参数为“t” T型和第二种,功能型“体”,接受????的功能什么都不返回(单位)

我看到这个符号Something。() - &gt;有些东西经常使用,即Anko:

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

但我不认为它在任何地方被解释过。()意味着......

3 个答案:

答案 0 :(得分:25)

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()

因此它是TR的通用函数,第一个参数是“{1}}类型的接收者”,第二个是T扩展函数类型,它扩展了{ {1}},返回由f返回的T类型。

例如,您可以像这样使用它:

R


请参阅此处的扩展功能文档:
kotlinlang.org/docs/reference/lambdas.html#extension-function-expressions
kotlinlang.org/docs/reference/extensions.html

<强>加了:

  

所以唯一有效的with是为T?

定义的任何0参数函数

不是真的。在Kotlin function types and extension function types are unified中,它们可以互换使用。例如,我们可以传递String :: length,其中函数val threadInfoString = with (Thread.currentThread()) { // isDaemon() & getPriority() are called with new property syntax for getters & setters "${getName()}[isDaemon=$isDaemon,priority=$priority]" } 是预期的。

f

类似(String) -> Int&amp;的类型// map() expects `(String) -> Int` // argument has type `String.() -> Int` strings.map(String::length) 在背景方面是相同的 - 事实上,接收器是第一个参数。

因此,以下任何函数都适用于Thread.() -> String参数:

(Thread) -> String

或者您可以像Thread.() -> String一样使用function literalfun 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 ),但只有在可以从上下文中推断出接收器类型时它才有效。

答案 1 :(得分:5)

这是另一个令人惊讶的概念,名为带有接收器的函数文字,它看起来与扩展函数类似,区别在于它具有 "receiver"

inline fun doSomethingWithInt(receiver: Int.() -> Unit) {

    5.receiver() //Possible as receiver is Int type

    receiver(5) //possible as receiver should be passed as first Argument
}

让我们分开吧

<强> (receiver: Int.() -> Unit)

与常规lambda () -> Unit有什么不同之处是它有接收器类型为 Int

与Extension函数类似,此接收器可以在 Int 类型

上调用

<强> 5.receiver()

根据Documentation Here

  

可以使用其调用(...)调用函数类型的值   运营商:

     

f.invoke(x)或只是f(x)。

     

如果值具有接收器类型,则应传递接收器对象   作为第一个论点。另一种调用函数值的方法   带接收器的类型是将它与接收器对象一起添加,就好像   该值是一个扩展函数:1.foo(2)

所以你也可以写 receiver(5)

现在我们可以编写 DSL样式代码了。我们来看看kotlin标准库函数Apply

public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

正如您所见,apply是T的扩展函数,将与接收器类型 T

一起使用

由于T。() T将作为lambda中的第一个参数。

现在这里的块由函数体内的 block()调用,但你也可以写 this.block()或block(this)

在调用此lambda 后,我们将返回T的实例(调用apply的相同实例)

所以,我们在apply中做的是在参数中使用lambda,在调用它的同一个实例T上执行它,并返回相同的T实例

实施例

调用此函数将如下所示:

(StringBuilder("Hello ").apply({ append("Kotliner") }))

但是在kotlin中,如果lambda是最后一个参数,那么你可以简单地写funName({})而不是写funName{}

所以上面的代码也可以写成

StringBuilder("Hello ").apply {
        append("Kotliner")
        append("! ")
    }

看起来更清晰简洁。所以Kotlin这样就提供了像Groovy这样的DSL结构。

这是关于同一主题的very nice blog

答案 2 :(得分:0)

它被称为“带有接收器的函数文字”

函数类型可以有一个附加的接收器类型,该类型在符号中的点之前指定:类型A.(B)-> C表示可以在A的接收器对象上使用参数B调用的函数。并返回C值。带接收器的函数文字常与这些类型一起使用。

您可以在kotlin官方文档中找到答案:Function literals with receiver