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

10,601

Solution 1

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!")
    }
}

Solution 2

Extending @humazed answer as compiler complains that

lambda argument should be moved out of parenthesis

setPositiveButton("ok"){_,_ -> doSomething()}
Share:
10,601

Related videos on Youtube

Elye
Author by

Elye

Android Design, Development and Deployment

Updated on September 14, 2022

Comments

  • Elye
    Elye over 1 year

    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?

  • Prime624
    Prime624 over 5 years
    The (terrible) Android Developers Guide tells people to use SAM. Thanks for explaining why it's bad.
  • humazed
    humazed about 5 years
    My guess this is from the days when Java was the only language, and the engineer responsible for converting docs to support kotlin didn't bother to change the code to use the kotlin way and just convert the java code to kotlin. or maybe he creates a script to convert it to automate his job :D
  • Manish Chandra Joshi
    Manish Chandra Joshi about 2 years
    Why would you use SAM in kotlin? while it has native support for functions. Because its easier to document a functional interface, its purpose and its function compared to using kotlin's function syntax on the fly. For example, accepting Compartor interface is much more readable than, taking (T1, T2) -> boolean, because comparator interface's compare method is well documented in its own file.