Мне интересно, как я могу реализовать простой шаблон публикации-подписки в kotlin с такими API:
Channel.publish(event: T)
Channel.subscribe{ event: T -> Unit)
Мне важно знать тип, так что Channel
будет доставлять только события типа T
только подписчику типа (T)->Unit
(а не другому типу (S)->Unit
, который S is T
равен false
)
Вот моя реализация.
Но две вещи меня беспокоят. Посмотрите:
import kotlin.reflect.KClass
object Channel {
private val subscribers: MutableMap<KClass<*>, (Any) -> Unit> = mutableMapOf()
inline fun <reified T> publish(event: T) {
subscribers[T::class]?.invoke(event as Any)
}
inline fun <reified T> subscribe(noinline subscriber: (T) -> Unit) {
subscribers[T::class] = subscriber as (Any) -> Unit
}
}
data class Person(val name: String)
fun main() {
Channel.subscribe { person: Person -> println("Hello ${person.name}") }
Channel.publish(Person("John"))
}
Броски event as Any
и subscriber as (Any) -> Unit
кажутся мне глупыми. Как я могу избавиться от этого? Возможно ли в этой проблеме?
ОБНОВЛЕНИЕ № 1:
Я нашел решение избавиться от event as Any
inline fun <reified T : Any> publish(event: T) {
subscribers[T::class]?.invoke(event)
}