https://kotlinlang.org logo
Title
c

crummy

12/07/2018, 12:23 AM
Still wrestling with generics. Is it possible to do this simple event handler?
class EventManager{
    private val listeners: MutableMap<KClass<out Event>, MutableList<EventListener<in Event>>> = HashMap()

    fun <T : Event> register(event: KClass<out T>, listener: EventListener<T>) {
        val eventListeners: MutableList<EventListener<T>> = listeners.getOrPut(event) { ArrayList() }
        eventListeners.add(listener)
    }

    fun notify(event: Event) {
        listeners[event::class]?.forEach { it.handle(event) }
    }
}
My
getOrPut
call wants a
MutableList<EventListener<T>>
but found
MutableList<EventListener<in Event>>
instead.
p

Pavlo Liapota

12/07/2018, 9:43 AM
I guess you cannot do it in type safe way for a compiler. You need to do an unsafe cast. Example: https://play.kotlinlang.org/#eyJ2ZXJzaW9uIjoiMS4zLjExIiwicGxhdGZvcm0iOiJqYXZhIiwiYXJncyI6IiIsImpzQ29kZSI6IiIsIm5vbmVNYXJrZXJzIjp0cnVlLCJ0aGVtZSI6ImlkZWEiLCJmb2xkZWRCdXR0b24iOnRydWUsInJlYWRPbmx5IjpmYWxzZSwiY29kZSI6Ii8qKlxuICogWW91IGNhbiBlZGl0LCBydW4sIGFuZCBzaGFyZSB0aGlzIGNvZGUuIFxuICogcGxheS5rb3RsaW5sYW5nLm9yZyBcbiAqL1xuXG5pbXBvcnQga290bGluLnJlZmxlY3QuS0NsYXNzXG5cbmZ1biBtYWluKCkge1xuICAgIHZhbCBldmVudE1hbmFnZXIgPSBFdmVudE1hbmFnZXIoKVxuICAgIGV2ZW50TWFuYWdlci5yZWdpc3RlcihvYmplY3QgOiBFdmVudExpc3RlbmVyPEV2ZW50MT4ge1xuICAgICAgICBvdmVycmlkZSBmdW4gaGFuZGxlKGV2ZW50OiBFdmVudDEpIHsgcHJpbnRsbihcImV2ZW50MSBoYW5kbGVyMVwiKSB9XG4gICAgfSlcbiAgICBldmVudE1hbmFnZXIucmVnaXN0ZXIob2JqZWN0IDogRXZlbnRMaXN0ZW5lcjxFdmVudDE+IHtcbiAgICAgICAgb3ZlcnJpZGUgZnVuIGhhbmRsZShldmVudDogRXZlbnQxKSB7IHByaW50bG4oXCJldmVudDEgaGFuZGxlcjJcIikgfVxuICAgIH0pXG4gICAgZXZlbnRNYW5hZ2VyLnJlZ2lzdGVyKG9iamVjdCA6IEV2ZW50TGlzdGVuZXI8RXZlbnQyPiB7XG4gICAgICAgIG92ZXJyaWRlIGZ1biBoYW5kbGUoZXZlbnQ6IEV2ZW50MikgeyBwcmludGxuKFwiZXZlbnQyXCIpIH1cbiAgICB9KVxuICAgIFxuICAgIHByaW50bG4oXCJUcmlnZ2VyaW5nIGV2ZW50MVwiKVxuICAgIGV2ZW50TWFuYWdlci5ub3RpZnkoRXZlbnQxKCkpXG4gICAgXG4gICAgcHJpbnRsbihcIlRyaWdnZXJpbmcgZXZlbnQyXCIpXG4gICAgZXZlbnRNYW5hZ2VyLm5vdGlmeShFdmVudDIoKSlcbn1cblxuY2xhc3MgRXZlbnRNYW5hZ2VyIHtcbiAgICBwcml2YXRlIHZhbCBsaXN0ZW5lcnM6IE11dGFibGVNYXA8S0NsYXNzPG91dCBFdmVudD4sIE11dGFibGVMaXN0PEV2ZW50TGlzdGVuZXI8RXZlbnQ+Pj4gPSBIYXNoTWFwKClcblxuICAgIGlubGluZSBmdW4gPHJlaWZpZWQgVCA6IEV2ZW50PiByZWdpc3RlcihsaXN0ZW5lcjogRXZlbnRMaXN0ZW5lcjxUPikge1xuICAgICAgICByZWdpc3RlcihsaXN0ZW5lciwgVDo6Y2xhc3MpXG4gICAgfVxuICAgIFxuICAgIGZ1biA8VCA6IEV2ZW50PnJlZ2lzdGVyKGxpc3RlbmVyOiBFdmVudExpc3RlbmVyPFQ+LCBldmVudENsYXNzOiBLQ2xhc3M8b3V0IFQ+KSB7XG4gICAgICAgIHZhbCBldmVudExpc3RlbmVycyA9IGxpc3RlbmVycy5nZXRPclB1dChldmVudENsYXNzKSB7IEFycmF5TGlzdCgpIH1cbiAgICAgICAgZXZlbnRMaXN0ZW5lcnMuYWRkKGxpc3RlbmVyIGFzIEV2ZW50TGlzdGVuZXI8RXZlbnQ+KVxuICAgIH1cblxuICAgIGZ1biBub3RpZnkoZXZlbnQ6IEV2ZW50KSB7XG4gICAgICAgIGxpc3RlbmVyc1tldmVudDo6Y2xhc3NdPy5mb3JFYWNoIHsgaXQuaGFuZGxlKGV2ZW50KSB9XG4gICAgfVxufVxuXG5pbnRlcmZhY2UgRXZlbnRMaXN0ZW5lcjxpbiBUIDogRXZlbnQ+IHtcbiAgICBmdW4gaGFuZGxlKGV2ZW50OiBUKTtcbn1cblxuc2VhbGVkIGNsYXNzIEV2ZW50KClcblxuY2xhc3MgRXZlbnQxKCkgOiBFdmVudCgpXG5cbmNsYXNzIEV2ZW50MigpIDogRXZlbnQoKSJ9
c

crummy

12/07/2018, 10:31 AM
Wow, thank you - and the reified trick is great too, I couldn't figure that out. Much appreciated!
I asked this on SO as well, I posted your answer there as well for posterity - I hope that's OK. https://stackoverflow.com/a/53667770/281657
🆗 1