Kotlin的generics:generics映射参数中的types不匹配
我有以下使用generics的代码:
abstract class Event(val name: String) interface ValueConverter { fun convert(event: E): Float fun getEventClass(): Class } class ValueConverters { private val converters = HashMap<String, ValueConverter>() fun register(converter: ValueConverter) { converters.put(converter.getEventClass().name, converter) } fun unregister(eventClass: Class) { converters.remove(eventClass.name) } fun convert(event: E): Float { return converters[event.javaClass.name]?.convert(event) ?: 0.0f } fun clear() { converters.clear() } }
但在这条线上:
converters.put(converter.getEventClass().name, converter)
它给出了一个错误:
types不匹配。 预期的ValueConverter 。 findValueConverter 。
我也尝试过这样的事情:
class ValueConverters { private val converters = HashMap<String, ValueConverter>() fun register(converter: ValueConverter) { converters.put(converter.getEventClass().name, converter) } fun unregister(eventClass: Class) { converters.remove(eventClass.name) } fun convert(event: Event): Float { return converters[event.javaClass.name]?.convert(event) ?: 0.0f } fun clear() { converters.clear() } }
但问题是当调用ValueConverters.register()
类似的东西时:
class SampleEvent1 : Event(name = SampleEvent1::class.java.name) class SampleValueConverter1 : ValueConverter { override fun convert(event: SampleEvent1): Float = 0.2f override fun getEventClass(): Class = SampleEvent1::class.java } converters.register(converter = SampleValueConverter1())
它也给出类似的types不匹配错误。
我应该如何声明generics,以便我可以使用任何实现ValueConverter的类并接受任何扩展Event的类?
错误在这一行:
private val converters = HashMap
此映射的值仅限于ValueConverter
。 所以,如果你有一个class级
class FooEvent : Event
和一个值转换器:
ValueConverter
,
您无法在地图中存储该值转换器。 你真正想要的是*
星形投影types。
private val converters = HashMap
现在你可以把任何值转换器放在地图上。
但是,这揭示了另一个问题:如何
fun
知道地图中返回转换器的通用types是什么? 毕竟,地图可能包含不同事件types的多个转换器!
IntelliJ立即抱怨:
convert(event: E): Float { val converter = converters[event.javaClass.name] ?: return 0.0f return (converter as ValueConverter
如果您好奇为什么编译器没有早先抱怨您的转换器函数:请记住您的映射只能容纳ValueConverter
并且只能保存该类? 这意味着编译器知道你可以将任何Event
子类传递给这个转换器。 一旦你改变为星型投影types,编译器不知道这是否可能是一个ValueConverter
,或一个ValueConverter
,等等 – 使一个给定的转换器的有效函数签名在你的地图convert(event: Nothing)
:
因为没有什么是有效的输入。