Store lambda in a variable in kotlin
Asked Answered
B

3

23

I'm starting developing in Android with kotlin and I have a problem with lambdas. I have a function to set a listener in my view, this looks like this:

fun setListener(listener: () -> Unit) {
}

The problem is that the code passed as lambda won't be executed in setListener function, it will be executed in another part of my code (specifically when an item of a spinner is selected) so I have to "save" or "store" this lambda into a variable/property so that I'm able to execute it when needed. Any idea about how to do it?

Edit: I've achieved it by doing:

private var listener: (() -> Unit)? = null

fun setListener(listener: () -> Unit) {
    this.listener = listener
}

Is there a better way to do it? Thanks

Bruch answered 5/5, 2017 at 18:27 Comment(0)
A
24

Here's how you can do it:

class Foo {
    private var listener: () -> Unit = {}
    fun setListener(listener: () -> Unit) {
        this.listener = listener
    }
}

However, manually writing setters is discouraged in Kotlin. Instead, you can just make your property public:

class Foo {
    var listener: () -> Unit = {}
}

For reference, here are the docs about properties with lots of examples.

Amphitropous answered 5/5, 2017 at 18:44 Comment(1)
"Getter visibility must be the same as property visibility" (i.e. you cannot have public set with private get). I suggest var listener: () -> Unit = {}.Wade
N
14

You can store a function in a property easily. The simplest way:

var listener: (() -> Unit)? = null

Usage:

foo.listener = { println("called") }

If you want your property to be set-only, you can create one public property with unusable getter and one private property for internal use. Full example:

class Example {

    // for internal use
    private var _listener: (() -> Unit)? = null

    // public set-only
    var listener: (() -> Unit)?
        @Deprecated(message = "set-only", level = DeprecationLevel.ERROR)
        get() = throw AssertionError() // unusable getter
        set(value) { _listener = value } // write-through setter

    fun somethingHappend() {
        _listener?.invoke()
    }
}
Naughty answered 5/5, 2017 at 19:2 Comment(4)
With this code I get an error also when trying to use _listener inside my classBruch
@Bruch I've augumented & clarified my answer. If you're still getting error, post error message.Naughty
You could just make the getter private with private get() = .... Then you don't even need the _listener property.Randers
@Randers you can't set setter vilibility lower than getter visibility.Naughty
P
1

Here is a simple example.

fun main(){
    val result=::sum //function assign to variable (first method)
    val result1: (first: Int, second: Int) -> Int=::sum //function assign to variable (second method)
    print(result(5,6))

}
fun  sum(first:Int,second:Int):Int{
    return first+second;
}
Photothermic answered 25/3, 2021 at 16:22 Comment(1)
This answer should be marked as correct solution : the =:: is the keyDuet

© 2022 - 2024 — McMap. All rights reserved.