我正在探索并積極使用 Kotlin 生產中的泛型。
Kotlin 泛型對我來說是一個大難題,所以也許你可以解釋并幫助我理解與 Java 相比它在這里是如何作業的。
我有課AbstracApiClient(不是很抽象)
class AbstracApiClient {
open protected fun makeRequest(requestBuilder: AbstractRequestBuilder) {
// ...
}
}
AbstractRequestBuilder (不是很抽象):
open class AbstractRequestBuilder {
...
}
ConcreteApiClient繼承的AbstractApiClient應該覆寫 makeRequestConcreteRequestBuilder繼承自AbstractRequestBuilder:
class ConcreteApiClient: AbstractApiClient() {
protected override fun makeRequest(requestBuilder: ConcreteRequestBuilder) {
// ...
}
}
class ConcreteRequestBuilder: AbstractRequestBuilder()
因為我會有更具體的 API 客戶端。我想做一個抽象,我可以傳遞繼承的具體請求構建器并覆寫`make requests 方法。
- 我嘗試按原樣使用它,但不起作用
- 我試過這個符號,
protected open fun <R: ApiRequestBuilder> make request(request builder: R)但它不會匹配我想要的覆寫函式:protected override fun make request(request builder: ConcreteRequestBuilder)
我還有什么其他選擇?我在這里錯過了什么嗎?
注意:在這種情況下我不能使用interface或abstract classes,所以理想情況下我想找到一種繼承和函式覆寫的方法。
uj5u.com熱心網友回復:
您不能覆寫具有更具體引數型別的方法,因為它破壞了Liskov 的替換原則:
val client: AbstractApiClient = ConcreteApiClient()
client.makeRequest(AbstractRequestBuilder())
正如您在上面看到的,ConreteApiClient實作必須能夠處理父類的所有可能輸入,因為它可以通過父類的 API 訪問。
為了做你想做的事,你需要通過泛型來限制父類本身:
open class AbstractApiClient<R : AbstractRequestBuilder> {
open protected fun makeRequest(requestBuilder: R) {
// ...
}
}
class ConcreteApiClient: AbstractApiClient<ConcreteRequestBuilder>() {
protected override fun makeRequest(requestBuilder: ConcreteRequestBuilder) {
// ...
}
}
這樣, 的任何實體AbstractApiClient<R>都必須顯示它接受哪種型別的請求構建器(在型別引數中)。它可以防止上述問題,因為現在父型別也攜帶資訊:
// doesn't compile
val client: AbstractApiClient<AbstractRequestBuilder> = ConcreteApiClient()
// this compiles
val client: AbstractApiClient<ConcreteRequestBuilder> = ConcreteApiClient()
我試過這個符號 protected open fun <R: ApiRequestBuilder> make request(request builder: R)
現在這方面的嘗試,這是行不通的,因為如果你做的方法一般(不是類),這意味著該方法的每個實作必須處理所有型別的R(而不是一個R每實作)。將泛型放在類上允許為類的每個實體指定一次泛型引數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/375632.html
下一篇:禁止通用函式中物件的非列舉鍵
