SoFunction
Updated on 2025-03-03

Detailed explanation of sam (functional interface) in Kotlin

Use lambda expression to represent anonymous class instances in java

When using java to set up a button, we usually create anonymous class instances, as follows

(new OnClickListener()){
  @Override
  public void onClick(View v){
    (this,"Hello World",Toast.LENGTH_LONG).show()
  }
}

In kotlin we can use a lambda expression to replace this instance

btn_test.setOnClickListener { view : View ->
      (this,"Hello World",Toast.LENGTH_LONG).show()
}

The reason why it can be implemented in this way is that the OnClickListener interface has only one abstract method. This interface is regarded as a functional interface or a SAM interface in kotlin. SAM represents a single abstract method, and similar functional interfaces such as Runnable and Callable.

Pass lambda as a parameter to a Java method

We define a

void postponeComputation(int delay,Runnable computation){
}

Then use the lambda expression to pass the Runnable parameter

postponeComputation(1000){
    print("hello world")
}

Note that the lambda argument compiler will automatically convert it into a Runnable instance. This call method is the same as the display implementation of a Runnable anonymous object.

postponeComputation(1000,object : Runnable{
    override fun run(){
        println(42)
    }
})

But the actual difference is that each time this statement is called, the Runnable object will be created repeatedly, and using the lambda expression as an argument will only create one object if no function variables that customize it are accessed.

If you want to be completely equivalent, you need to define it like this

val runnable = Runaable{ println(42) }
fun handleComputation(){
   postponeComputation(1000,runnable)
}

In addition, if variables are captured from the scope surrounding it, the same instance will not be reused every time the call is called. The following call will use a new Runnable instance every time.

fun handleComputation(id : String){
   postponeComputation(1000){println(id)}
}

In fact, starting from kotlin1.0, each lambda will be compiled into an anonymous class. If the lambda captures a variable, each captured variable will have corresponding fields in the anonymous class.

SAM construction method: explicitly convert lambda into functional interface.

In some methods, a functional interface needs to be returned, and a lambda cannot be returned. It can be wrapped with the SAM construction method.

fun createAllDoneRunable() : Runnable{
  return Runnable{ println(“All done”) }
}

The SAM function name is the same as the underlying functional interface name. The SAM constructor only receives one parameter - a lambda used as a single abstract method body of a functional interface, and returns an instance of the interface class.

In addition to creating a functional interface through lambda, the functional interface generated by lambda can also be placed in a variable, as follows

val listener = OnClickListener{
  view -> val text = when(){
    .button1 -> “First button”
    .button2 -> “Second button”
    else -> “Unknown button"
  }
  toast(text)
}
(listener)
(listener)

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.