generics - 如何在构造函数调用中引用实例方法
问题描述
我正在 Kotlin 中编写一些基于协程的事件处理代码,并且进展顺利。我在各种事件处理程序中有代码,它们做同样的事情,我试图把这段代码放在一个地方。我被困在以下问题上。这个想法是子类可以通过提供类到方法的映射来指定可以处理的事件类型。我无法编译它。有没有办法使这项工作?有更好的方法吗?谢谢。
abstract class EventHandler(private val handlers: Map<KClass<out Event>, suspend (Event) -> Unit>) {
suspend fun handle(event: Event) {
val handler = handlers[event::class]
if (handler != null) {
handler(event)
} else {
throw IllegalStateException("No handler configured for $event")
}
}
}
data class ExampleEvent(private val id: String): Event
class ExampleHandler(): EventHandler(mapOf(ExampleEvent::class to handleExample)) {
^^^^^^^^^^^^^ - compile error
suspend fun handleExample(event: ExampleEvent) {
TODO()
}
}
解决方案
由于 3 个不同的原因,您无法编译它:
由于
handleExample
它是一个实例方法,因此您不能在超级构造函数中引用它,因为您的子类的实例尚未创建。如果你想要一个实例方法的函数引用,你应该在它前面加上前缀
::
,所以在你的情况下::handleExample
。该函数
handleExample
接受类型的事件,ExampleEvent
因此它不符合输入 typeEvent
,在这种情况下,您需要进行强制转换。
也就是说,您的问题有一个解决方案,它解决了上述 3 点以及为每个EventHandler
子类重复该样板的负担。
解释都在评论里。
inline fun <reified T : Event> typedCoroutine(crossinline block: suspend (T) -> Unit): Pair<KClass<out Event>, suspend (Event) -> Unit> =
// Since the type is reified, we can access its class.
// The suspend function calls the required suspend function casting its input.
// The pair between the two is returned.
T::class to { event -> block(event as T) }
abstract class EventHandler {
// Require the subclasses to implement the handlers.
protected abstract val handlers: Map<KClass<out Event>, suspend (Event) -> Unit>
suspend fun handle(event: Event) {
val handler = handlers[event::class]
if (handler != null) {
handler(event)
} else {
throw IllegalStateException("No handler configured for $event")
}
}
}
class ExampleHandler : EventHandler() {
// The type of typedCoroutine is inferred from handleExample.
override val handlers: Map<KClass<out Event>, suspend (Event) -> Unit> = mapOf(typedCoroutine(::handleExample))
suspend fun handleExample(event: ExampleEvent) {
TODO()
}
}
使用typedCoroutine
您可以轻松地在所有子类中填充handlers
地图EventHandler
。
推荐阅读
- angular - Angular 订阅被多次调用
- r - 在 R 中导入文本文件时如何避免“输入中没有可用的行”错误?
- wordpress - WooCommerce - 为非注册用户获取发货国家
- spring-boot - Spring boot 安全性、API 密钥保护或 oauth2 resourceServer 用于相同资源
- c - gcc 在我的系统上生成什么汇编语言?
- node.js - 应该在客户端还是服务器端完成长时间运行的视频处理任务
- javascript - 带有指示器 CSS 的幻灯片
- reactjs - 如何在反应中添加或删除输入字段
- node.js - 无法解析以获取令牌
- ruby-on-rails - REST API 响应取决于发出请求的人