我正在尝试围绕一个非常常见的模式来通用化样板文件,而 Kotlin 让我非常接近。
我构建了一个充当监听器管理器的类,如下所示:
class GenericListenerSupport <EventArgumentType, ListenerFunction: (EventArgumentType) -> Unit> {
private val listeners = mutableListOf<ListenerFunction>()
fun addListener(listener: ListenerFunction) {
listeners.add(listener)
}
fun removeListener(listener: ListenerFunction) {
listeners.remove(listener)
}
fun fireListeners(argument: EventArgumentType) {
listeners.forEach { it.invoke(argument) }
}
}
它可以按如下方式使用:
class ExampleWithArgument {
private val listenerSupport = GenericListenerSupport<String, (String)->Unit>()
fun exampleAdd() {
listenerSupport.addListener({ value -> System.out.println("My string: "+value)})
}
fun exampleFire() {
listenerSupport.fireListeners("Hello")
}
}
到目前为止,一切都很好。但如果听者没有论据怎么办?或者进一步延伸,多个参数。
我可以用这个勉强度日:
class ExampleWithNoArgument {
private val listenerSupport = GenericListenerSupport<Nothing?, (Nothing?)->Unit>()
fun exampleAdd() {
listenerSupport.addListener({ System.out.println("I've got no argument")})
}
fun exampleFiring() {
listenerSupport.fireListeners(null)
}
}
但是有味道,而且显然多个参数没有用。
有没有更好的方法来实现这一点?例如支持这个概念的东西:
private val listenerSupport = GenericListenerSupport<???, (String, Double)->Unit>()
最佳答案
由于您的 GenericListenerSupport
声明了一个类型参数 EventArgumentType
并期望在 fun fireListeners(argument: EventArgumentType)
中有一个它的实例,我怀疑您可以以干净的方式支持多个参数。相反,我建议使用数据类(这不是太多额外的代码),作为包装多个值的干净且类型安全的方法:
data class MyEvent(val id: String, val value: Double)
private val listenerSupport = GenericListenerSupport<MyEvent, (MyEvent) -> Unit>()
至于不传递值,还可以使用Unit
,只有一个值的类型Unit
:
listenerSupport.fireListeners(Unit)
类型系统和解析不允许您在需要单个参数的情况下不传递任何参数,但是,如 @Ruckus T-Boom建议,您可以在需要 Unit
的地方进行扩展来触发没有值的监听器:
fun GenericListenerSupport<Unit>.fireListeners() = fireListeners(Unit)
有点离题,但我认为如果您不需要自定义函数类型并且 (EventArgumentType) -> Unit
就足够了,您可以简化类型:
class GenericListenerSupport<EventArgumentType> {
/* Just use `(EventArgumentType) -> Unit` inside. */
}
关于android - Kotlin、泛型和可能没有参数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45987685/