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

Kotlin中子类类型对象的克隆实现问题

解决方案:Kotlin实现自类型克隆接口

问题根源分析

  1. 最初的Kotlin接口错误:
    接口中定义的fun <T:Foo> copy():T是泛型方法,要求调用者可以指定任意Foo子类作为返回类型,但Bar的copy只能固定返回Bar,无法满足泛型方法的多态要求,因此编译失败。而Java能编译是因为泛型擦除机制,编译时不严格检查泛型匹配,但这种写法在运行时可能引发类型转换异常,并不严谨。

  2. 改写后的接口与addFoo函数的问题:

    • 接口泛型参数名Foo与接口名重复,造成混淆,应该使用更清晰的命名(如Self)。
    • addFoo函数的泛型约束T:Foo是原始类型约束,此时f.copy()返回的是模糊的Foo类型,而非具体的T;同时错误地给无泛型参数的copy()方法添加了<T>类型参数,导致编译报错。

正确实现方案

1. 定义自类型克隆接口

使用泛型参数明确表示接口的自身类型,避免模糊性:

interface Foo<out Self> {
    fun copy(): Self
}

2. 实现类正确继承接口

让Bar类实现Foo<Bar>,明确copy方法返回自身类型:

class Bar(private val v: Int) : Foo<Bar> {
    override fun copy(): Bar = Bar(v)
}

3. 修正addFoo函数的泛型约束

将泛型约束改为T : Foo<T>,确保T的copy方法返回的就是T类型,同时移除不必要的泛型参数调用:

fun <T : Foo<T>> addFoo(
    foo: T,
    fooList: List<T>,
): MutableList<T> {
    val result = mutableListOf<T>()
    for (f in fooList) {
        val newF = f.copy() // 无需指定泛型参数,copy返回的就是T类型
        result.add(newF)
    }
    result.add(foo)
    return result
}

验证代码

fun main() {
    val bar1 = Bar(1)
    val bar2 = bar1.copy()
    println(bar2.v) // 输出:1

    val originalList = listOf(Bar(2), Bar(3))
    val newList = addFoo(Bar(4), originalList)
    newList.forEach { println(it.v) } // 输出:2、3、4
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:48:23