Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redundant SAM-constructor can't be remove for Kotlin declared function, but works on Java declared function

Tags:

java

kotlin

I have a Java Class function as below

public void setPositiveButton(int resId, DialogInterface.OnClickListener listener) 

I also have the same Kotlin Class function as below

fun setPositiveButton(resId: Int, listener: DialogInterface.OnClickListener)

When I call them from a Kotlin code

    javaClassObj.setPositiveButton(R.string.some_string,
            DialogInterface.OnClickListener { _, _ -> someFunc()})

    kotlinClassObj.setPositiveButton(R.string.some_string,
            DialogInterface.OnClickListener { _, _ -> someFunc()})

The Java Class function call could be reduced, but not the Kotlin Class function

    javaClassObj.setPositiveButton(R.string.some_string,
            { _, _ -> someFunc()})

    kotlinClassObj.setPositiveButton(R.string.some_string,
            DialogInterface.OnClickListener { _, _ -> someFunc()})

Why can't the Kotlin function call reduce the redundant SAM-Constructor as per enabled for Java?

like image 429
Elye Avatar asked Sep 05 '17 09:09

Elye


2 Answers

Extending @humazed answer as compiler complains that

lambda argument should be moved out of parenthesis

setPositiveButton("ok"){_,_ -> doSomething()}
like image 148
asim Avatar answered Nov 05 '22 04:11

asim


Why would you use SAM in kotlin? while it has native support for functions.

The SAM convention is used in java8 as a workaround not having native function support.

from kotlin doc#sam-conversions:

Note that SAM conversions only work for interfaces, not for abstract classes, even if those also have just a single abstract method.

Also, note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

you should then declare a function directly.

fun setPositiveButton(resId: Int, listener: (DialogInterface, Int) -> Unit) {
    listener.invoke(
            //DialogInterface, Int
    )
}

and then it can be used

setPositiveButton(1, { _, _ -> doStuff() })

In kotlin 1.4 you can use SAM conversions for Kotlin classes.

fun interface Listener {
    fun listen()
}

fun addListener(listener: Listener) = a.listen()

fun main() {
    addListener {
        println("Hello!")
    }
}
like image 14
humazed Avatar answered Nov 05 '22 05:11

humazed