Комбинируйте различные типы параметров, используя единый универсальный интерфейс в Kotlin

#generics #kotlin

#универсальные параметры #kotlin

Вопрос:

Допустим, у нас есть следующие переменные:

 private val subscriptions1 = ArrayList<(String) -> Unit>()
private val subscriptions2 = ArrayList<(Int) -> Unit>()
private val subscriptions3 = ArrayList<(Char) -> Unit>()
  

Возможно ли объединить их в одну карту следующим образом?

 private val subscriptions = ConcurrentHashMap<KClass<*>, ArrayList<(KClass<*>) -> Unit>>()
  

Следующий код не компилируется с переменной subscriptions , как я определил это выше:

 inline fun <reified T : Any> send(event: T) {
    val eventSubscriptions = getSubscriptionsOnEvent(T::class)
    for (eventProcessor in eventSubscriptions) {
        eventProcessor(event)
    }
}
  

Ответ №1:

(KClass<*>) -> Unit Означает тип функции, которая принимает KClass<*> в качестве параметра. За лямбдами скрываются функциональные интерфейсы. Лучшей альтернативой является внедрение вашего собственного интерфейса, например

 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
    }
}
  

Чтобы сократить пример, можно заменить Callback интерфейс универсальной лямбда-функцией (Any) -> Unit . На практике, возможно, имеет смысл включить что-то еще в интерфейс, так что, вероятно, это все еще имеет смысл

Комментарии:

1. Это интересно. Я буду использовать это как решение. Спасибо!