Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using functional interfaces with function types in Kotlin

When calling Java code from Kotlin, there is SAM conversion so that Java code like this:

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

Can 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 create an instance of this class and try to invoke the setter function, I do it like so:

val thing = SomeClass()

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

I'm aware that Kotlin has function types therefore doesn't support SAM conversion from various sites such as this one.

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

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

val thing = SomeClass()

thing.setOnSomeActionListener { parameter1, parameter2 ->
    // Do stuff here
}

.

like image 572
Farbod Salamat-Zadeh Avatar asked Jul 12 '17 08:07

Farbod Salamat-Zadeh


People also ask

Can we define function in interface in Kotlin?

In Kotlin, the interface works exactly similar to Java 8, which means they can contain method implementation as well as abstract methods declaration. An interface can be implemented by a class in order to use its defined functionality.

Can you implement multiple interfaces in Kotlin?

Extending a Class and Implementing Two Interfaces First, like Java, a Kotlin class can only inherit one superclass, but it can implement multiple interfaces.

What are different types of functional interfaces?

Runnable, ActionListener, Comparable are some of the examples of functional interfaces.

What is function functional interface?

function Description. Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method, called the functional method for that functional interface, to which the lambda expression's parameter and return types are matched or adapted.


1 Answers

A function type looks like this:

(Parameters) -> ReturnType

In your case, instead of using the interface type, you could use (View, Int) -> Unit. It would 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 functional types you can also specify names for the parameters. 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 a type alias

To avoid having to type (View, Int) -> Unit every time, you can define a typealias:

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

So that your code now looks like this again:

private var onSomeActionListener: OnSomeActionListener? = null

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

And to call it:

val thing = SomeClass()

thing.setOnSomeActionListener { view, position ->
    // Do stuff here
}
like image 197
RobCo Avatar answered Sep 21 '22 05:09

RobCo