Using functional interfaces with function functions in Kotlin

When calling Java code from Kotlin, there is a SAM transformation so that the Java code looks like this:

adapter.setOnClickListener(new OnClickListener() { @Override public void onClick(View view, int position) { // Do stuff here } }); 

It might look like this:

 adapter.setOnClickListener { view, position -> // Do stuff } 

Now I'm working on a Kotlin project, and I want to define a functional interface as an event listener:

 interface OnSomeActionListener { fun onSomeAction(parameter1: Int, parameter2: String) } 

In SomeClass I have a function to set the listener:

  ... private var onSomeActionListener: OnSomeActionListener? = null fun setOnSomeActionListener(listener: OnSomeActionListener) { onSomeActionListener = listener } ... 

And when I instantiate this class and try to call the setter function, I do it like this:

 val thing = SomeClass() thing.setOnSomeActionListener(object : OnSomeActionListener { override fun onSomeAction(parameter1: Int, parameter2: String) { // Do stuff here } }) 

I know that Kotlin has functional types, so it does not support SAM conversion from various sites such as this one .

I read a little about function types, but have not used them before.

How can I rewrite my code so that I can call the setter function like this?

 val thing = SomeClass() thing.setOnSomeActionListener { parameter1, parameter2 -> // Do stuff here } 

.

+5
source share
3 answers

The type of function is as follows:

 (Parameters) -> ReturnType 

In your case, instead of using an interface type, you can use (View, Int) -> Unit . It will look something like this:

 private var onSomeActionListener: ((View, Int) -> Unit)? = null fun setOnSomeActionListener(listener: (View, Int) -> Unit) { onSomeActionListener = listener } private fun callSomeActionListener(view: View, position: Int) { onSomeActionListener?.invoke(view, position) } 

Add names

In function types, you can also specify parameter names. This doesn't change much under the hood, but they can add some clarity here and in the calling code, which is nice.

 (view: View, position: Int) -> Unit 

Using type alias

To avoid having to enter (View, Int) -> Unit each time, you can define typealias:

 typealias OnSomeActionListener = (view: View, position: Int) -> Unit 

So now your code looks like this:

 private var onSomeActionListener: OnSomeActionListener? = null fun setOnSomeActionListener(listener: OnSomeActionListener?) { onSomeActionListener = listener } 

And to call him:

 val thing = SomeClass() thing.setOnSomeActionListener { view, position -> // Do stuff here } 
+9
source

Something like that:

 // declare a variable of nullable function type: var onSomeActionListener: ((Int, String) -> Unit)? = null // declare higher-order function: fun setOnSomeActionListener(listener: (Int, String) -> Unit) { onSomeActionListener = listener } // set listener: val listener: (Int, String) -> Unit = { p1, p2 -> { /* some stuff */ } } setOnSomeActionListener(listener) // or in one line: setOnSomeActionListener { p1, p2 -> { /* some stuff */ } } 

For More Information: Higher Order Functions and Lambdas

0
source

How to define a function that takes a function and returns an interface?

 fun makeOnSomeActionListener(f: (Int,String) -> Unit) = object : OnSomeActionListener { override fun onSomeAction(parameter1: Int, parameter2: String) = f(parameter1, parameter2) } 

The interface delegates its work f .

Then you can write

 val thing = SomeClass() thing.setOnSomeActionListener(makeOnSomeActionLisener { parameter1, parameter2 -> // Do stuff here }) 
0
source

Source: https://habr.com/ru/post/1269750/


All Articles