Kotlin中子类类型对象的克隆实现问题
解决方案:Kotlin实现自类型克隆接口
问题根源分析
最初的Kotlin接口错误:
接口中定义的fun <T:Foo> copy():T是泛型方法,要求调用者可以指定任意Foo子类作为返回类型,但Bar的copy只能固定返回Bar,无法满足泛型方法的多态要求,因此编译失败。而Java能编译是因为泛型擦除机制,编译时不严格检查泛型匹配,但这种写法在运行时可能引发类型转换异常,并不严谨。改写后的接口与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
相关产品推荐
相关产品推荐

