使用泛型搭配when语句时出现类型不匹配问题求助
问题描述
尝试在when语句中使用泛型时,复制传入参数出现编译错误,代码示例如下:
abstract class A { abstract val prop: String}; data class B(override val prop: String) : A(); fun <T : A> execute(t: T): T { return when (t) { is B -> { t.copy() // 无法编译 // t.copy() as T // 可以编译 } else -> t } }
不进行强制类型转换时,会得到如下编译错误:
error: type mismatch: inferred type is Line_19.B but T was expected
请问为什么编译器无法识别类型是一致的?有没有办法避免强制类型转换?
问题分析与解决方案
编译器无法识别类型一致的原因
泛型T : A只限定了T是A的子类,但编译器无法确定T就是B——比如存在class C : B()时,调用execute<C>(C("test")),t是C类型,进入is B分支后t.copy()返回B,但方法要求返回T(即C),这会导致类型不匹配。因此编译器不会默认T和B是同一类型,只能确认B是A的子类,无法将其等同于T。
避免强制类型转换的方案
方案一:使用具体化泛型(reified)+ 内联函数
通过reified让编译器在编译期获取T的具体类型,结合类型检查确保copy()结果安全适配T:
abstract class A { abstract val prop: String } data class B(override val prop: String) : A() inline fun <reified T : A> execute(t: T): T { return when (t) { is B -> { check(T::class == B::class) { "传入类型与泛型不匹配" } t.copy() as T // 此处强转安全,已通过reified泛型验证T就是B } else -> t } }
方案二:给父类添加自类型泛型的抽象copy方法
让父类定义返回子类自身类型的抽象copy方法,子类实现时返回自己的类型,无需类型判断就能保证返回值符合T:
abstract class A<T : A<T>> { abstract val prop: String abstract fun copy(): T } data class B(override val prop: String) : A<B>() { // 数据类自动生成的copy方法返回B,直接复用即可 override fun copy(): B = super.copy() } fun <T : A<T>> execute(t: T): T { return t.copy() }
这种方式更优雅,完全摆脱了强制类型转换和分支判断,扩展性也更好——新增A的子类时,只需实现对应的copy方法即可。
内容的提问来源于stack exchange,提问作者Markinho
相关产品推荐
相关产品推荐

