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

使用泛型搭配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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 07:20:34