我有這樣一個場景,我有一個使用 Kotlin 發出不同型別事件的超級抽象類sealed classes。
這些事件建模如下。
sealed class BaseEvent {
object ConnectionStarted : BaseEvent()
object ConnectionStopped : BaseEvent()
}
sealed class LegacyEvent : BaseEvent() {
object TextChanged : LegacyEvent()
object TextCleared : LegacyEvent()
}
sealed class AdvancedEvent : BaseEvent() {
object ButtonClick : AdvancedEvent()
object ButtonLongClick : AdvancedEvent()
}
這是發出這些事件的類
abstract class BaseViewModel<E : BaseEvent> {
private fun startConnection() {
emit(BaseEvent.ConnectionStarted) // <-- Error
}
fun emit(event: E){
//...
}
}
class LegacyBaskan : BaseViewModel<LegacyEvent>() {
fun textChanged() {
emit(LegacyEvent.TextChanged) // <-- Works
}
}
class AdvancedBaskan : BaseViewModel<AdvancedEvent>() {
fun buttonClicked() {
emit(AdvancedEvent.ButtonClick) // <-- Works
}
}
在這里,它只適用于子類,我可以在它們的關聯類中LegacyEvent或AdvancedEvent在它們的關聯類中發出任何事件。但是,對于BaseBaskan該類,BaseEvent雖然我宣告泛型型別E必須擴展BaseEvent.
我需要每個子類都可以訪問自己的事件以及超類事件,但不能訪問其他子類的事件。
我怎樣才能仍然從BaseEvent基類中發出事件,同時讓每個類都可以只發出自己的事件?
uj5u.com熱心網友回復:
不確定您是否對為什么它不讓您從基類發出專案感到困惑。由于 E 可以是 BaseEvent 的任何子型別,如果您的類可以發出ConnectionStarted,那么在任何時候將其宣告為BaseViewModel<AnythingBesidesConnectionStarted>.
我能想到的唯一方法是擁有該emit功能的私有和公共版本。您可能需要更改班級中其他地方未顯示的代碼。如果有某個函式回傳E,則必須更改它以使其回傳BaseEvent。
abstract class BaseViewModel<E : BaseEvent> {
private fun startConnection() {
emitInternal(BaseEvent.ConnectionStarted)
}
private fun emitInternal(event: BaseEvent) {
//...
}
fun emit(event: E){
emitInternal(event)
}
}
uj5u.com熱心網友回復:
您不能發出BaseEvent.ConnectionStartedin BaseViewModel(以及其他事件),因為E尚未定義,因此型別系統無法確定您不會發出破壞泛型型別不變性的另一個子型別的事件。
只需添加一個多載的私有版本,它接受BaseEvent引數(您需要一些@JvmName注釋以使其可編譯為 JVM 目標):
abstract class BaseViewModel<E : BaseEvent> {
private fun startConnection() {
emit(BaseEvent.ConnectionStarted)
}
@JvmName("emitBaseEvent")
private fun emit(event: BaseEvent) {
//...
}
fun emit(event: E) {
emit(event as BaseEvent)
}
}
uj5u.com熱心網友回復:
看起來您需要逆變,這可以使用in. 假設您的基類只有諸如emit使用型別E作為引數型別而不是回傳型別的方法,那么:
abstract class BaseViewModel<in E : BaseEvent> {
請參閱https://kotlinlang.org/docs/generics.html#use-site-variance-type-projections。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/335832.html
上一篇:用值初始化泛型類
下一篇:打字稿通用聯合決議順序
