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 interop)。必要ない場合は、単にタイプエイリアスを使用できます(Kotlin 1.1以降) :
typealias EventHandler<T> = (T) -> Unit
この場合、単純なラムダがすぐに機能します。
ただし、タイプエイリアスを使用したくない場合は、問題が解決しません。 KotlinはJavaで定義された関数に対してのみSAM変換を行うということです。 Events.handler
はKotlinで定義されているため、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
型の名前付きエイリアスに置き換えられるため、必要ありません。