2015-11-08 79 views
28

在Java中,我們可以做到這一點 Events.handler(Handshake.class, hs -> out.println(hs));Kotlin:使用lambda代替功能界面?

在科特林但是我試圖複製的行爲來取代這個:

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

enter image description here

更優選的,但是我想使用的東西更短這樣的: 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) 

} 
+1

您是否爲第一個參數嘗試了'Handshake :: class.java'?無論如何,請嘗試按Ctrl + P查看該函數的可能參數。 –

+1

'Events.handler(Handshake :: class){println(it.sent)}' - 此語法與內聯函數無關 –

+0

OP不理解內聯函數的含義。 –

回答

41

假設下面你確實需要EventHandler作爲一個單獨的接口(例如爲Java互操作)。如果不這樣做,你可以簡單地用一個類型別名(因爲科特林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) 

注意:當科特林的未來版本的類型是別名,該EventHandler接口將不再需要,因爲它會替換爲類型的命名別名(T) -> Unit

+0

經過一些修改,我得到了這個適合我的情況。結果代碼:http://pastebin.com/tsLfFxnq謝謝! – Jire

+0

此外,我還可以通過'KClass'工作,它可以在這裏查看:http://pastebin.com/mEWhA5yc – Jire

+0

@andrey,我們是否具有上述特性(在需要SAM的地方使用函數)在Kotlin現在? – mhshams