Kotlin中如何通过接口调用实现类的copy函数?
解决方案
方法一:在接口中定义参数修改方法(推荐)
核心思路是让FooInterface提供抽象方法来生成修改param后的新实例,每个实现类利用自身的copy方法完成实现,既保留data class的不可变特性,又保证扩展性。
修改后的接口与实现类
interface FooInterface { val param: String // 定义修改param的方法,返回新实例 fun withParam(newParam: String): FooInterface } data class Foo(override val param: String) : FooInterface { override fun withParam(newParam: String): Foo { // 利用data class自动生成的copy方法创建新实例 return copy(param = newParam) } } data class Bar(override val param: String) : FooInterface { override fun withParam(newParam: String): Bar { return copy(param = newParam) } }
使用方式
由于Kotlin data class是不可变的,我们需要生成新列表而非修改原实例:
val list: List<FooInterface> = listOf(Foo("abc"), Bar("def")) val updatedList = list.map { it.withParam("test") }
这种方式符合开闭原则,新增FooInterface实现类时,只需实现withParam方法即可,无需修改原有逻辑。
方法二:使用扩展函数封装类型判断(适合无法修改接口的场景)
如果无法修改原FooInterface,可以用扩展函数封装类型判断逻辑,避免在业务代码中重复强转:
// 为FooInterface扩展修改param的方法 fun FooInterface.withParam(newParam: String): FooInterface = when(this) { is Foo -> copy(param = newParam) is Bar -> copy(param = newParam) else -> throw IllegalArgumentException("Unsupported type: ${this::class.simpleName}") } // 使用方式和方法一一致 val list: List<FooInterface> = listOf(Foo("abc"), Bar("def")) val updatedList = list.map { it.withParam("test") }
这种方式的缺点是新增实现类时需要修改扩展函数,但相比在业务代码中到处强转,已经更整洁。
内容的提问来源于stack exchange,提问作者Maddin
相关产品推荐
相关产品推荐

