Kotlin:使用lambda代替功能界面?
在Java中,我们可以这样做Events.handler(Handshake.class, hs -> out.println(hs));
但是在Kotlin中,我试图复制这个行为来取代这个:
Events.handler(Handshake::class, object : EventHandler<Handshake> { override fun handle(event: Handshake) { println(event.sent) } })
用更方便:
Events.handler(Handshake::class, EventHandler<Handshake> { println(it.sent) })
出于某种原因参考EventHandler
:
更好的是,但是我想使用更短的东西,像这样: Events.handler(Handshake::class, { println(it.sent) })
或者使用广告的功能来使用这样的方法: Events.handler(Handshake::class) { println(it.sent) }
这是我的Events
对象:
import java.util.* import kotlin.reflect.KClass object Events { private val map = HashMap<Class<*>, Set<EventHandler<*>>>() fun <T : Any> handler(eventType: KClass<T>, handler: EventHandler<T>) { handler(eventType.java, handler) } fun <T> handler(eventType: Class<T>, handler: EventHandler<T>) = handlers(eventType).add(handler) fun post(event: Any) = handlers(event.javaClass).forEach { it.handle(event) } operator fun plus(event: Any) = post(event) private fun <T> handlers(eventType: Class<T>): HashSet<EventHandler<T>> { var set = map[eventType] if (set == null) { set = HashSet<EventHandler<*>>() map.put(eventType, set) } return set as HashSet<EventHandler<T>> } }
和我的EventHandler
接口:
@FunctionalInterface interface EventHandler<T> { fun handle(event: T) }
假设下面,你真的需要EventHandler
作为一个单独的接口(例如Java互操作)。 如果你不这样做,你可以简单地使用一个类型别名(自Kotlin 1.1以来):
typealias EventHandler<T> = (T) -> Unit
在这种情况下,一个简单的lambda将立即工作。
但是如果你不想使用类型别名,问题依然存在。 Kotlin只对Java中定义的函数进行SAM转换。 由于在Kotlin中定义了Events.handler
,所以SAM转换不适用于它。
为了支持这个语法:
Events.handler(Handshake::class, EventHandler<Handshake> { println(it.sent) })
你可以定义一个名为EventHandler
的函数:
fun <T> EventHandler(handler: (T) -> Unit): EventHandler<T> = object : EventHandler<T> { override fun handle(event: T) = handler(event) }
为了支持这个语法:
Events.handler(Handshake::class, { println(it.sent) })
或这个:
Events.handler(Handshake::class) { println(it.sent) }
您需要重载handler
函数来取代EventHandler
的函数:
fun <T> Events.handler(eventType: Class<T>, handler: (T) -> Unit) = EventHandler(handler)
注意:当未来版本的Kotlin具有类型别名时,不需要EventHandler
接口,因为它将被替换为类型(T) -> Unit
的命名别名(T) -> Unit