What does a Kotlin function signature with T.() mean?

前端 未结 3 869
星月不相逢
星月不相逢 2021-01-30 13:00

This is a standard Kotlin function (as far as I know)

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

But could anyone write

3条回答
  •  故里飘歌
    2021-01-30 13:43

    This is another amazing concept named Function literals with receiver, It looks similar with extension function with difference that it has "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
    }
    

    Let's break this apart

    (receiver: Int.() -> Unit)

    How this is different from Regular lambda like () -> Unit is it has receiver which is Type of Int

    So similar to Extension function this receiver can invoke on Int type

    5.receiver()

    And as per the Documentation Here

    A value of a function type can be invoked by using its invoke(...) operator:

    f.invoke(x) or just f(x).

    If the value has a receiver type, the receiver object should be passed as the first argument. Another way to invoke a value of a function type with receiver is to prepend it with the receiver object, as if the value were an extension function: 1.foo(2)

    So You can also write receiver(5)

    Now we can write DSL style code because of this. Let's see kotlin standard library function Apply

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

    As you can see apply is an Extension function of T, block will be function with receiver type T,

    Because of T.() T will be available as the first argument in lambda.

    Now here block is invoked by block() inside function body, but you can also write this.block() or block(this)

    And after invoking this lambda we will return instance of T(same instance on which apply is called)

    So, what we did in apply is took lambda in argument, executed it on same instance T on which it was called, and return the same T instance

    Example

    Calling of this function will look like:

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

    But in kotlin if lambda is last argument then instead of writing like funName({}) you can simply write funName{}.

    so above code can be also written as

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

    which looks more clear and concise. So this way Kotlin provides DSL structure like Groovy.

    This is very nice blog about same Topic

提交回复
热议问题