簡體   English   中英

在 Kotlin 中使用約束泛型實現抽象類

[英]Implement abstract class with constrained generic in Kotlin

在 Kotlin 1.3.61 上工作

有這個代碼:

abstract class ResourceObserver<T> : Observer<T> where T : Resource<T> {
    override fun onChanged(t: T) {
        when (t.status) {
            Status.LOADING -> { ... }
            Status.ERROR -> { ... }
            Status.SUCCESS -> { onSuccess(t.data) }
        }
    }

    abstract fun onSuccess(data: T?)
}

並嘗試實施它

private val foo = object : ResourceObserver<Resource<Bar>> {
    override fun onSuccess(data: Bar?) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}

編譯器(在本例中為 Android Studio)給我這個錯誤:

Type argument is not within its bounds.
Expected: Resource<Resource<Bar>>
Found: Resource<Bar>

我明顯錯誤的代碼有什么問題?

where T: Resource<T>的約束確實要求您為T使用的任何類型參數也必須是Resource<T>T由類型本身替換)。

根據此約束,您為實現T:= Resource<Bar>提供的類型參數將被檢查為Resource<T> ≡ Resource<Resource<Bar>>並且未通過此檢查。

要使此約束和子類型起作用, Bar需要是Resource<Bar>的子類型(實現)。

您真的需要T成為具有相同TReosurce<T>嗎? 如果您使用帶星投影的上限T: Resource<*>或添加另一個類型參數,它會解決您的問題嗎,如下所示?

abstract class ResourceObserver<T, R> : Observer<T> where T : Resource<R> { ... }

private val foo = object : ResourceObserver<Resource<Bar>, Bar> { ... }

這看起來像是在嘗試使用F-bounded polymorphism 為了讓它工作,你需要

  1. 使Bar擴展Resource<Bar>

  2. 制作private val foo = object: ResourceObserver<Bar> {... }而不是<Resource<Bar>>

通常Resource本身將被聲明為具有類似的約束

class Resource<T : Resource<T>>

所以如果你忘記做 1 Bar將無法編譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM