我試圖有一個object收集兒童班的聽眾Message。
typealias Listener <T> = (T) -> Unit
object MessageRegistry {
private val listeners = mutableMapOf<KClass<out Message>, MutableSet<Listener<Message>>>()
fun <T : Message> listen(clazz: KClass<T>, listener: Listener<T>) {
listeners.getOrPut(clazz) { mutableSetOf() }.add(listener)
}
}
我希望這個物件的客戶注冊他們的監聽器,如下ConnectedMessage所示Message:
MessageRegistry.listen(ConnectedMessage::class) { connectedMessage: ConnectedMessage ->
doSomething(connectedMessage)
}
但是,方法似乎有問題MessageRegistry.listen()。我無法listener添加到MutableSet<Listener<Message>>>.
listener有一個(T) -> Unit具有泛型的型別T,
我想將其添加到<T: Message>type中。MutableSet(Message) -> Unit
我收到如下型別錯誤:
Type mismatch.
Required:
Listener<Message> /* = (Message) → Unit */
Found:
Listener<T> /* = (T) → Unit */
正如我提到的T繼承Message類(<T : Message>),我認為這是一個有效的轉換。
我還嘗試標記out為的泛型型別Listener:
private val listeners = mutableMapOf<KClass<out Message>, MutableSet<Listener<out Message>>>()
但它給出了以下錯誤:
Conflicting projection in type alias expansion in intermediate type '(T) -> Unit'
我可以做些什么來讓聽眾在一個集合中?
提前致謝。
uj5u.com熱心網友回復:
你的 Listener 是一個 T 消費者,而不是生產者,所以它不能被賦予一個型別out Message并且仍然有用。
由于您的函式允許 Listener 使用 Message 的子型別,但 Listener 是消費者,因此您的 Listener 無法滿足成為Listener<Message>. 例如,如果您有 aListener<SubMessage>并試圖將 a 傳遞Message給它,那將是不安全的,因為Messagea 可能不是 a SubMessage。
但是,由于您將這些與類一起存盤在 Map 中,因此您有效地創建了型別的運行時安全性,并且您可以從邏輯上推斷型別在匹配時可以安全地轉換。
因此,泛型系統不能保證安全,但如果你小心你的施法位置,你可以。你可以像這樣實作它:
object MessageRegistry {
private val listeners = mutableMapOf<KClass<out Message>, MutableSet<Listener<*>>>()
fun <T : Message> listen(clazz: KClass<T>, listener: Listener<T>) {
listeners.getOrPut(clazz) { mutableSetOf() }.add(listener)
}
private fun <T: Message> getListeners(clazz: KClass<T>): MutableSet<Listener<T>> {
@Suppress("UNCHECKED_CAST")
return listeners[clazz] as MutableSet<Listener<T>>
}
}
我建議將這些行內/具體化以使您的代碼在呼叫站點上更簡單。在大多數情況下,它將能夠在呼叫站點推斷型別,因此您不必顯式傳遞它。
object MessageRegistry {
private val listeners = mutableMapOf<KClass<out Message>, MutableSet<Listener<*>>>()
@PublishedApi
internal fun <T : Message> listen(clazz: KClass<T>, listener: Listener<T>) {
listeners.getOrPut(clazz) { mutableSetOf() }.add(listener)
}
inline fun <reified T : Message> listen(noinline listener: Listener<T>) {
listen(T::class, listener)
}
private fun <T: Message> getListeners(clazz: KClass<T>): MutableSet<Listener<T>> {
@Suppress("UNCHECKED_CAST")
return listeners[clazz] as MutableSet<Listener<T>>
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/474116.html
上一篇:打字稿:為什么類泛型不能分配給從`this`推斷的相同泛型?
下一篇:Flutter泛型函式回呼
