Kotlin:使用lambda代替function界面?

在Java中,我们可以这样做Events.handler(Handshake.class, hs -> out.println(hs));

但是在Kotlin中,我试图复制这个行为来取代这个:

 Events.handler(Handshake::class, object : EventHandler { override fun handle(event: Handshake) { println(event.sent) } }) 

用更方便:

Events.handler(Handshake::class, EventHandler { println(it.sent) })

出于某种原因参考EventHandler

在这里输入图像说明

更好的是,但是我想使用更短的东西,像这样: Events.handler(Handshake::class, { println(it.sent) })

或者使用广告的function来使用这样的方法: 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  handler(eventType: KClass, handler: EventHandler) { handler(eventType.java, handler) } fun  handler(eventType: Class, handler: EventHandler) = handlers(eventType).add(handler) fun post(event: Any) = handlers(event.javaClass).forEach { it.handle(event) } operator fun plus(event: Any) = post(event) private fun  handlers(eventType: Class): HashSet<EventHandler> { var set = map[eventType] if (set == null) { set = HashSet<EventHandler>() map.put(eventType, set) } return set as HashSet<EventHandler> } } 

和我的EventHandler接口:

 @FunctionalInterface interface EventHandler { fun handle(event: T) } 

假设下面,你真的需要EventHandler作为一个单独的接口(例如Java互操作)。 如果你不这样做,你可以简单地使用一个types别名(自Kotlin 1.1以来):

 typealias EventHandler = (T) -> Unit 

在这种情况下,一个简单的lambda将立即工作。

但是如果你不想使用types别名,问题依然存在。 Kotlin只对Java中定义的函数进行SAM转换。 由于Events.handler是在Kotlin中定义的,所以SAM转换不适用于它。

为了支持这个语法:

 Events.handler(Handshake::class, EventHandler { println(it.sent) }) 

你可以定义一个名为EventHandler的函数:

 fun  EventHandler(handler: (T) -> Unit): EventHandler = object : EventHandler { override fun handle(event: T) = handler(event) } 

为了支持这个语法:

 Events.handler(Handshake::class, { println(it.sent) }) 

或这个:

 Events.handler(Handshake::class) { println(it.sent) } 

您需要重载handler函数来取代EventHandler的函数:

 fun  Events.handler(eventType: Class, handler: (T) -> Unit) = EventHandler(handler) 

注意:当未来版本的Kotlin具有types别名时,不需要EventHandler接口,因为它将被替换为types(T) -> Unit的命名别名(T) -> Unit