Adding a custom listener to a kotlin class


#1

i am sorry if my question is stupid, but i realize that my mind still seems to be suck in the strictly object orientated java way of thinking and don’t know how to solve my problem with kotlin, although i already read the documentation of kotlin and followed some tutorials.

right now i dont know how to add a custom listener to a class. here is an example of how i would do it with java.

public class Test {

    private OnActionListener onActionListenerListener;

    public Test(OnActionListener onActionListenerListener){
        this.onActionListenerListener = onActionListenerListener;
    }

    public interface OnActionListener {
        void onAction();
    }

    public void doAction(){
        this.onActionListenerListener.onAction();
    }
}

class Test2{

    public Test2(){
        Test test = new Test(new Test.OnActionListener() {
            public void onAction() {
                // do something
            }
        });
        test.doAction();
    }
}

as far as i understand kotlin does not need objects for that, so there must be a way how to store a function and set it from outside. how do i do that?


#2

That would be something like this:

fun main(args: Array<String>) {
	val test = Test {
        // do something
        println("actually do something")
    }
    test.doAction()
}

class Test(private val onActionListenerListener: () -> Unit) {
    fun doAction() {
        onActionListenerListener()
    }
}

The big difference is with the () -> Unit declaration.Which is just a general purpose interface (Function) since there is probably no need to define a specific one.


#3

thanks, but i already did something like this, and it worked fine; i was able to use the function passed as argument for my purpose, but i wonder if its possible to store this function somewhere like a property. or is this a wrong way of thinking?.

what if i dont pass this function in the constructor but want to add it later if its necessary?


#4

finally i was able to answer my question on my own. this is the kotlin code i was searching for.

class Test {
    var onAction = fun(x: Int, y: Int): Int = null!!
    fun doAction() {
        onAction(1, 2)
    }
}

class Test2{
    fun testFun(){
        var test = Test()
        test.onAction = fun(x, y): Int {
            return x + y    
        }
    }
}

#5

Instead of this weird null!! thing to throw an exception of it is uninitialized, the kotlin idiom would be:

lateinit var onAction: (Int, Int) -> Int

#6

Assuming returning an Int from the function is a typo as I do not see this in the Java code, I would assign a no-operation function to the variable so you do not risk a null pointer exception:

var onAction = { x: Int, y: Int -> }

Unless, of course, it is an error to not have initialized onAction.


#7

@jstuyts: your example does not work when i try to assign a function to it. i also did not understand why you assume that Int is a typo. anyway the solution of @dalewking works and compiles perfectly fine, so i consider my question as answered.


#8

In your Java example you use:

void onAction();

If you need a return value you can only initialize the variable if there is a reasonable default.

If you cannot assign a function to the variable, I suspect you are either using the wrong signature or declared a val. It works fine for me:

var x = { x: Int, y: Int -> 0 }
x = { a, b ->  a + b }

#10

sorry, i forgott that i wrote example java code at the beginning, i understand now and it also works.actually i like your solution even more as i dont have to care if this function is set or not, and never get any exception.