簡體   English   中英

如何在 Kotlin 中使用繼承的 class 覆蓋方法?

[英]How to override method with inherited class in Kotlin?

我正在探索並積極在生產中使用 generics 和 Kotlin。

Kotlin + generics 對我來說是一個大難題,所以與 Java 相比,也許你可以在這里解釋並幫助我理解它是如何工作的。

我有 class AbstracApiClient (不是很抽象)

class AbstracApiClient {
  
  open protected fun makeRequest(requestBuilder: AbstractRequestBuilder) {
    // ... 
  }
}

AbstractRequestBuilder (不是很抽象):

open class AbstractRequestBuilder {
  ...
}

繼承AbstractApiClientConcreteApiClient應該使用從AbstractRequestBuilder繼承的ConcreteRequestBuilder覆蓋 makeRequest :

class ConcreteApiClient: AbstractApiClient() {
  
  protected override fun makeRequest(requestBuilder: ConcreteRequestBuilder) {
    // ... 
  }
}

class ConcreteRequestBuilder: AbstractRequestBuilder()

因為我會有更具體的 API 客戶端。 我想做一個抽象,我可以傳遞繼承的具體請求構建器並覆蓋`make requests 方法。

  1. 我嘗試按原樣使用它但不起作用
  2. 我試過這個表示法protected open fun <R: ApiRequestBuilder> make request(request builder: R)但它不匹配覆蓋 function 我希望它是: protected override fun make request(request builder: ConcreteRequestBuilder)

我還有什么其他選擇? 我在這里錯過了什么嗎?

注意:在這種情況下,我不能使用interfaceabstract classes ,所以理想情況下,我想找到一種使用 inheritance 和函數覆蓋的方法。

您不能使用更具體的參數類型覆蓋方法,因為它違反了Liskov 的替換原則

val client: AbstractApiClient = ConcreteApiClient()

client.makeRequest(AbstractRequestBuilder())

正如您在上面看到的, ConreteApiClient實現必須能夠處理父類 class 的所有可能輸入,因為它可以通過父類的 API 訪問。

要做你想做的,你需要通過 generics 限制父 class 本身:

open class AbstractApiClient<R : AbstractRequestBuilder> {
  
  open protected fun makeRequest(requestBuilder: R) {
    // ... 
  }
}

class ConcreteApiClient: AbstractApiClient<ConcreteRequestBuilder>() {
  
  protected override fun makeRequest(requestBuilder: ConcreteRequestBuilder) {
    // ... 
  }
}

這樣, AbstractApiClient<R>的任何實例都必須顯示它接受哪種類型的請求構建器(在 type 參數中)。 它可以防止上述問題,因為現在父類型也攜帶信息:

// doesn't compile
val client: AbstractApiClient<AbstractRequestBuilder> = ConcreteApiClient() 

// this compiles
val client: AbstractApiClient<ConcreteRequestBuilder> = ConcreteApiClient()

我試過這個符號保護的開放樂趣 <R: ApiRequestBuilder> 發出請求(請求生成器:R)

現在關於這個嘗試的實現,它不起作用,因為如果你使方法通用(不是class ),這意味着該方法的每個實現都必須處理各種R (不是一個R )。 將泛型放在 class 上允許為 class 的每個實例指定一次泛型參數。

暫無
暫無

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

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