【发布时间】:2020-04-26 01:13:44
【问题描述】:
在以下情况下,我找不到避免未经检查的强制转换的方法
class EventBus {
val eventToHandle: MutableMap<KClass<out Event>, Event.() -> Unit> = mutableMapOf()
final inline fun <reified T : Event> register(noinline handler: T.() -> Unit) {
@Suppress("UNCHECKED_CAST")
eventToHandle[T::class] = handler as Event.() -> Unit
}
fun fire(event: Event) {
eventToHandle[event::class]?.invoke(event)
?: throw IllegalStateException("Missing handler for class ${event::class}")
}
}
我的目标是强制映射仅包含具有 Event(或其子类型之一)作为接收者的 lambda,但同时我想要参考 actual 的实现Event 注册 lambda 时。
通过这种方式,我可以使用他的实现成员,而无需每次都进行强制转换。
一个例子(requestId是RequestExpiredEvent的一个字段):
eventBus.register<RequestExpiredEvent> {
requestService.setExpiredByRequestId(requestId)
}
我知道“消费者 lambda”没有协方差并且它们是逆变的,但我想是否有办法。 我发现一个丑陋的解决方法是:
final inline fun <reified T : Event> register(crossinline block: T.() -> Unit) {
val handler: Event.() -> Unit = { this as T; block(this) }
eventToHandle[T::class] = handler
}
谢谢
【问题讨论】:
-
你可以简化第二个版本
eventToHandle[T::class] = { block(this as T) },但这仍然会导致ClassCastException,实际上它与前一个没有区别