https://kotlinlang.org logo
#getting-started
Title
# getting-started
n

Norbi

02/29/2024, 10:46 AM
You guys always have very good explanations for my generics-related questions and misunderstandings, so the next question is... 😉 😄 I have a simple event bus implementation (backed by
MutableSharedFlow
):
Copy code
interface InProcessEventBus<E: Any> {

    suspend fun events(): Flow<E>

    suspend fun publish(event: E)
}
What I would like to achieve is to create a "view" of this event bus to handle only specific types of events, like:
Copy code
val globalEventBus: InProcessEventBus<Any> = ...
val constrainedEventBus: InProcessEventBus<SomeCustomEventClass> = globalEventBus // Do something with globalEventBus to make this compile
So the
constrainedEventBus
would be a view of the less specific
globalEventBus
, allowing only to publish and listen to more specific event types. Although I think this "subtyping" would be correct, the compiler does not think so 🙂 Currently my best solution is an unsafe cast but I hope you have a better idea:
Copy code
@Suppress("UNCHECKED_CAST")
fun <E: B, B: LocalEvent> InProcessEventBus<B>.constrain(): InProcessEventBus<E> = this as InProcessEventBus<E>

val constrainedEventBus = globalEventBus.constrain<SomeCustomEventClass, _>()
Thanks.
e

ephemient

02/29/2024, 11:36 AM
Nope, that's not safe.
Copy code
constrainedEventBus.events().collect { event: SomeCustomEventClass ->
would crash when
Copy code
globalEventBus.publish(NotSomeCustomEventClass())
is called
👍 1
if you want to receive a subset of the events, you'll have to do so yourself.
Copy code
inline fun <reified E: Any> InProcessEventBus<in E>.constrain(): InProcessEventBus<E> =
    object : InProcessEventBus<E> {
        override val events: Flow<E>
            get() = this@constrain.flow().filterIsInstance<E>()

        override fun publish(event: E) {
            this@constrain.publish(event)
        }
    }
1
🙏 1