Reputation: 558
Let's say we have the following variables:
private val subscriptions1 = ArrayList<(String) -> Unit>()
private val subscriptions2 = ArrayList<(Int) -> Unit>()
private val subscriptions3 = ArrayList<(Char) -> Unit>()
Is it possible to combine them into a single map in the following way?
private val subscriptions = ConcurrentHashMap<KClass<*>, ArrayList<(KClass<*>) -> Unit>>()
The following code doesn't compile with the variable subscriptions
as I have defined it above:
inline fun <reified T : Any> send(event: T) {
val eventSubscriptions = getSubscriptionsOnEvent(T::class)
for (eventProcessor in eventSubscriptions) {
eventProcessor(event)
}
}
Upvotes: 0
Views: 57
Reputation: 4992
The (KClass<*>) -> Unit
means a type of the function that takes KClass<*> as a parameter. There are hidden functional interfaces behind lambdas. The better alternative is to introduce your own interface instead, e.g.
interface Callback {
operator fun fun invoke(t: Any) : Unit //operator for better syntax
}
val subscriptions = ConcurrentHashMap<KClass<*>, List<Callback>>()
fun <reified T> subscribe<T>(action: (T) -> Unit) {
val wrapper = object: Callback {
override operator fun invoke(t: Any) {
action(t as T) ///inline function allows the cast
}
}
subscriptions[T::class] = (subscriptions[T::class] ?: listOf<Callback>()) + wrapper
}
//works as-is
inline fun <reified T : Any> send(event: T) {
val eventSubscriptions = getSubscriptionsOnEvent(T::class)
for (eventProcessor in eventSubscriptions) {
eventProcessor(event) /// Callback.invoke function is called implicitly
}
}
To shorten the example, it is possible to replace the Callback
interface with a generic lambda function (Any) -> Unit
. In practice, it might make sense to include something else to the interface, so probably, it still makes sense
Upvotes: 1