接口(interface)中的 Kotlin 内联函数

标签 kotlin interface inline

我想要一个接口(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/

相关文章:

spring-boot - 如何通过Jackson通过json轻松地在Redis中缓存Kotlin对象?

java - 新建文档时如何删除多个 "Attribute not allowed here error"?

android - 在 Kotlin 中使用 RxJava 进行数据转换

javascript - 在 Typescript 中将接口(interface)转换为函数参数

java - 为什么我们可以将 Java 接口(interface)转换为*任何*非最终类?

c# - 为什么将 List<Term> 的参数重构为 IEnumerable<Term>?

c++ - 内联关键字与标题定义

android - 在cardview中没有以下功能 Intent 错误

html - 如何链接整个(表格)按钮,而不是仅链接单词?

c++ - 将普通功能更改为模板会产生任何正/负差异吗?