You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何通过继承类重写父类方法并使用子类参数?

问题根因
  • 第一种直接替换参数类型的写法属于方法重载,并非重写:JVM的方法签名包含参数类型,父类makeRequest的入参是AbstractRequestBuilder,子类用ConcreteRequestBuilder作为入参的方法是全新的独立方法,调用父类类型实例时只会触发父类方法,不会走到子类逻辑。
  • 第二种方法级泛型的写法不符合泛型约束:方法上声明的<R: AbstractRequestBuilder>泛型的实际类型由调用方决定,不能由子类实现固定为某个具体类型,因此无法完成重写。
Kotlin与Java泛型的核心差异
  • 声明处型变支持:Kotlin可以直接在类/接口声明时用out(协变)、in(逆变)指定型变规则,Java仅支持使用点通配符? extends/? super实现型变。
  • 具体化类型参数:Kotlin的内联函数支持用reified关键字修饰泛型,运行时可以直接获取泛型的实际类型,Java不支持该特性。
  • 重写检查更严格:Kotlin对重写方法的参数、返回值类型匹配校验更严格,只要参数类型与父类不一致,加override关键字会直接编译报错,避免出现误以为是重写实际是重载的问题。
  • 无通配符捕获机制:Java的通配符存在复杂的捕获规则,Kotlin用声明处+使用处型变简化了该逻辑,不需要额外处理捕获问题。
可行实现方案

你可以将泛型声明在父类层面,由子类继承时指定具体的泛型类型,不需要修改原有父类的非抽象属性,完全符合你要求的继承+重写实现规则,同时兼容旧代码调用:

// 父类增加类级泛型约束,设置默认值兼容原有未指定泛型的调用逻辑
open class AbstractApiClient<R: AbstractRequestBuilder = AbstractRequestBuilder> {
    open protected fun makeRequest(requestBuilder: R) {
        // 原有逻辑保持不变
    }
}

open class AbstractRequestBuilder {
    // 原有逻辑保持不变
}

// 子类继承时指定对应RequestBuilder的具体类型即可正常重写
class ConcreteApiClient: AbstractApiClient<ConcreteRequestBuilder>() {
    override protected fun makeRequest(requestBuilder: ConcreteRequestBuilder) {
        // 子类自定义逻辑
    }
}

class ConcreteRequestBuilder: AbstractRequestBuilder()

后续新增其他API客户端时,只需要继承AbstractApiClient时传入对应RequestBuilder的实际类型即可,不需要修改父类逻辑。

内容的提问来源于stack exchange,提问作者Dmytro Chasovskyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:45:02