我想要一个接口(interface)并实现类似于以下内容的类/对象:
interface EventBus {
suspend fun <T : Message> publish(message: T)
suspend fun <R : Command, S : CommandResponse> request(command: R): Either<EventbusError, S>
suspend fun close(): Either<EventbusError, Unit>
//? fun <T : Message> subscribe(): Flow<T>
}
object EventBusImpl : EventBus {
private val _eventBus = MutableSharedFlow<Message>()
val messages = _eventBus.asSharedFlow()
override suspend fun <T : Message> publish(message: T) {}
override suspend fun <R : Command, S : CommandResponse> request(command: R): Either<EventbusError, S> {}
override suspend fun close(): Either<EventbusError, Unit> {}
inline fun <reified T:Message> subscribe():Flow<T> = messages.filterIsInstance<T>()
}
我知道内联函数不能被重写,因此不能成为接口(interface)的一部分,但作为 subscribe()
函数是 API 的重要组成部分,我仍然想在界面中以某种方式表示它,而不是返回到传递 Class<T>
作为一个论点。
如何实现这一点?
这个
interface EventBus {
suspend fun <T : Message> publish(message: T)
suspend fun <R : Command, S : CommandResponse> request(command: R): Either<EventbusError, S>
suspend fun close(): Either<EventbusError, Unit>
suspend fun <T : Message> subscribe(type: Class<T>): Flow<T>
}
当然可以,但不是很 Kotlin'ish
最佳答案
对您问题的评论是正确的:不可能有虚拟内联成员,因为必须在编译时知道实现才能内联它。
但是,您可以通过在界面中保留此虚拟成员来解决此问题:
suspend fun <T : Message> subscribe(type: Class<T>): Flow<T>
并添加此内联扩展函数:
suspend inline fun <reified T : Message> EventBus.subscribe() = subscribe(T::class)
现在您可以按照您的意愿使用订阅:
suspend fun foo(bus: EventBus) {
val flow = bus.subscribe<MyMessage>()
}
这样做的优点是在原始接口(interface)中保留subscribe
虚拟成员(因此它必须由子类型实现),并且通过内联扩展函数提供更好的调用语法。
关于接口(interface)中的 Kotlin 内联函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74517904/