繁体   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