Home > Net >  How kotlin decides parameter name in lambda?
How kotlin decides parameter name in lambda?

Time:06-07

I'm new to kotlin and I'm trying to develop a gradle plugin. The parameter name confuses me when I implement a Java function interface called org.gradle.api.Action.

My code.

val action: Action<AppliedPlugin> = Action { // Tip from IDEA "this:AppliedPlugin"
    
}

The function interface in Java.

public interface Action<T> {
    /**
     * Performs this action against the given object.
     *
     * @param t The object to perform the action on.
     */
    void execute(T t);
}

I'm confused by the tip, because I think parameter's default name is it not this.

Then I declared another Java function interface and implemented it. This time tip is it:AppliedPlugin!. Here is my code and temp function interface.

val temp: Temp<AppliedPlugin> = Temp { // Tip from IDEA "it:AppliedPlugin!"

}
public interface Temp<T> {

    void test(T t);
}

Can someone explain why kotlin use this as the default parameter name in the first lambda?

CodePudding user response:

Notice that org.gradle.api.Action<T> is marked with @HasImplicitReceiver, according to its documentation. The effect of HasImplicitReceiver is exactly that you can refer to the lambda parameter using this (which can be omitted most of the time):

Marks a SAM interface as a target for lambda expressions / closures where the single parameter is passed as the implicit receiver of the invocation (this in Kotlin, delegate in Groovy) as if the lambda expression was an extension method of the parameter type.

It's sort of like writing this in Kotlin, in the sense that this is the lambda parameter.

fun interface Action<T> {
    fun T.execute()
}

But the above is not exactly the same because you can only call execute in very few places, unlike the Java version.

This is useful in writing gradle plugins because having to type it. everywhere in your build.gradle isn't very nice.

Note that this is something specific to the Gradle APIs. In Kotlin in general, you wouldn't be able to do something like this. If you have a SAM interface like this:

public interface Action<T> {
    void execute(T t);
}

the lambda parameter is always it, or some other name that you give.

  • Related