Using lambdas does not compile when trying to pass in a method expecting a SAM interface

前端 未结 2 1423
旧时难觅i
旧时难觅i 2021-01-26 04:03

I am trying to understand lambdas and Kotlin. I created this trivial example

interface OnClickListener {
    fun onClick(s: String)
}

class Button {
    var cli         


        
2条回答
  •  梦毁少年i
    2021-01-26 04:56

    To be able to use a lambda, you need to use a Java interface.

    First, create a Java file and create an interface:

    public interface OnClickListener {
       void onClick(String s);
    }
    

    Then in your main:

       b.setOnClickListener(OnClickListener { s ->
            println(s)
       })
    

    As for your Button class:

    class Button {
     var clickListener: OnClickListener? = null //You can use this too but there's another way as well.
    
     //lateinit var clickListener: OnClickListener //Telling the compiler that you will initialize it later on.
    
     fun setOnClickListener(listener: OnClickListener) { //removed redundant ? from the function signature.
         clickListener = listener
     }
      fun click() {
         clickListener?.onClick("hello")  //Incase of lateinit, you don't need a '?' anymore
      }
    }
    

    SAM conversion only works between a Java code and a Kotlin code.

    EDIT: Since in Kotlin, you can store a function in a variable as well, here is my another two cents on how you can do it in a different way:

    class Button {
       lateinit var myFunction: (String) -> Unit
    
       fun setOnClickListener(block : (String) -> Unit) {
          myFunction = block //storing state of your 'listener'
       }
    
       fun onClick() = myFunction.invoke("Invoked from onClick function")
    }
    

    Then in your main:

    fun main() {
       val button = Button()
       button.setOnClickListener { s ->
           println(s)
       }
    
       button.onClick()
    }
    

提交回复
热议问题