Denver123
Denver123

Reputation: 23

Kotlin idiomatic way for passing a class to a function

I have a method which calls an object methods that wants a callback object as parameter. The callback object has to have 2 methods defined, onEvent1() and onEvent2().

One way is to do everything inline, but the result is that it's super-nested and becomes unreadable

myObj.method1(object : baseType {
     override fun onEvent1() {
               10 lines of nested code
     }
     override fun onEvent2() {
                more nested code
     }
)

I found it very unreadable given that a method is more 10 lines.

What is the best way to do this in Kotlin?

The only non-kotlin idiomatic way I know is to declare a class and pass an object of it, maybe inner class.

void mymethod() {
    class Obj : baseType {
              override fun onEvent1() {....}
              override fun onEvent2() {....}
    }
    
    val obj : Obj
    myObj.method1(obj)
}

Is there a better way?

Upvotes: 2

Views: 104

Answers (2)

Adam Millerchip
Adam Millerchip

Reputation: 23091

You could define a helper class that implements the callback type, and accepts the two callback functions (as you suggested):

class Callback(
    private val callback1: () -> Unit,
    private val callback2: () -> Unit
) : baseType {
    override fun onEvent1() = callback1()
    override fun onEvent2() = callback2()
}

Then write an extension function to wrap-up the use of the helper class:

fun MyObj.method1(callback1: () -> Unit, callback2: () -> Unit) =
    method1(Callback(callback1, callback2))

Then you can call it like this:

myObj.method1({ println("This is callback1") }, { println("This is callback2") })

Alternatively, you could just create an implementation of the callback class:

class Callback : baseType {
    override fun onEvent1() {
        // 10 lines of nested code
    }
    override fun onEvent2() {
        // more nested code
    }
}

And pass an instance of it to method1:

myObj.method1(Callback())

Upvotes: 2

Sam
Sam

Reputation: 9944

What if you used two lambdas for the two callbacks? The type of the lambda would be the type for the callback function: in your example () -> Unit, for a function that takes no arguments and returns a Unit result. First we make a new method that takes the two callbacks and wraps them up into a single object:

fun myMethod(callback1: () -> Unit, callback2: () -> Unit) {
    myObj.method1(object : baseType {
        override fun onEvent1() { callback1() }
        override fun onEvent2() { callback2() }
    })
}

Then we can call the new method like this:

myMethod(
    callback1 = { ... },
    callback2 = { ... }
)

It's a little more succinct than declaring a new object each time. Another benefit is that we can define the callbacks separately before passing them into the function:

val callback1 = { ... }
val callback2 = { ... }
myMethod(callback1, callback2)

Upvotes: 3

Related Questions