Egor Okhterov
Egor Okhterov

Reputation: 558

Combine different parameter types using single generic in Kotlin

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

Answers (1)

Eugene Petrenko
Eugene Petrenko

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

Related Questions