Skip to content

Instantly share code, notes, and snippets.

@orangy
Last active September 30, 2019 09:45
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save orangy/11178911 to your computer and use it in GitHub Desktop.
Save orangy/11178911 to your computer and use it in GitHub Desktop.
C#-style events in Kotlin
class Event<T> {
private val handlers = arrayListOf<(Event<T>.(T) -> Unit)>()
fun plusAssign(handler: Event<T>.(T) -> Unit) { handlers.add(handler) }
fun invoke(value: T) { for (handler in handlers) handler(value) }
}
val e = Event<String>() // define event
fun main(args : Array<String>) {
e += { println(it) } // subscribe
e("sdfsdf") // invoke
}
@MyErpSoft
Copy link

onTalk is null when Duck init at C#, but kotlin not support ref keyword.

class Delegate<TS, TA> : Event<TS, TA> {
    private var invocationList: MutableList<(TS, TA) -> Unit>? = null

    override operator fun plusAssign(m: (TS, TA) -> Unit) {
        val list = invocationList ?: mutableListOf<(TS, TA) -> Unit>().apply { invocationList = this }
        list.add(m)
    }

    override operator fun minusAssign(m: (TS, TA) -> Unit) {
        val list = invocationList
        if (list != null) {
            list.remove(m)
            if (list.isEmpty()) {
                invocationList = null
            }
        }
    }

    operator fun invoke(source: TS, arg: TA) {
        val list = invocationList
        if (list != null) {
            for (m in list)
                m(source, arg)
        }
    }
}

interface Event<out TS, out TA> {
    operator fun plusAssign(m: (TS,TA) -> Unit)
    operator fun minusAssign(m: (TS,TA) -> Unit)
}

class Duck {
    private val onTalk = Delegate<Duck, String>()
    val talking : Event<Duck,String> get() = onTalk

    fun poke() {
        onTalk(this, "Quaak!")
    }
}

fun main(args: Array<String>) {
    val duck = Duck()
    duck.talking += fun(s: Duck, a: String ) { println("${s.javaClass.name}: $a")}

    duck.poke()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment