【发布时间】:2016-03-13 18:11:40
【问题描述】:
好的,下面的代码是一个执行以下操作的事件系统:
- 将整数 id 分配给 lambda 表达式
- 将 lambda 的 id 放入事件的可变集合中
- 将整数 ID 映射到 lambda 表达式
- 返回 id(以后可用于从 lambda 中删除事件)
代码如下:
class EventHandler {
companion object {
val handlers = HashMap<KClass<out Event>, MutableSet<Int>>()
val idMap = HashMap<Int, (Event) -> Unit>();
/**
* @param event Class of the event you are registering
* @param handler What to do when the event is called
*/
fun <T : Event> register(event: KClass<T>, handler: (T) -> Unit): Int {
var id: Int = 0;
while(idMap[id] != null) {
id++;
}
var list = handlers.getOrPut(event, {mutableSetOf()});
list.add(id);
idMap[id] = handler;
return id;
}
}
}
这个方法的预期用途是这样的:
EventHandler.register(ChatEvent::class) { onChat ->
println(onChat.message)
}
以下行有错误:idMap[id] = handler;
错误是因为处理程序的类型为(T) -> Unit,尽管它需要为(Event) -> Unit 才能将其添加到idMap。虽然我在创建时说过T 应该扩展Event,所以这应该不是问题。如果有解决方案,有谁知道为什么会发生这种情况?
【问题讨论】:
-
有什么理由需要它是一个伴生对象而不是它自己的类?
-
@DougStevenson 因为我只打算有一个 EventHandler 实例。我尝试将其设为
object而不是class,但这并不能解决问题(如我所料) -
Kotlin 有自己的单例处理方式:kotlinlang.org/docs/reference/object-declarations.html
-
@DougStevenson 我也试过了,没用
-
它可以将任何事件作为参数,但它只能是基本类型 Event,而不是子类类型。就像常规方法一样,lambda 的参数类型必须在编译时绝对知道。它不能是模棱两可的或间接的。因此,如果这是您想要的,您必须将其转换为 lambda 以获得更具体的类型。