Kotlin中copy方法参数说明及接口适配data class copy的参数定义
Kotlin Data Class的copy方法参数
Kotlin编译器会自动为data class生成copy方法,它的参数对应data class的所有属性,且每个参数都带有默认值——默认值就是原对象该属性的当前值。
举个例子,若Foobar的定义为:
data class Foobar(val id: Int, val name: String, val active: Boolean = true) : Fizzbuzz
编译器生成的copy方法签名会是:
fun copy(id: Int = this.id, name: String = this.name, active: Boolean = this.active): Foobar
调用时只需传入需要修改的属性,比如foobar.copy(name = "newName"),未指定的属性会沿用原对象的值。
Fizzbuzz接口的clone方法参数设计
因为接口是抽象的,需兼顾扩展性,这里提供两种实用方案:
方案1:与特定实现类的copy参数强绑定(仅适用于接口仅服务Foobar的场景)
如果Fizzbuzz接口只针对Foobar设计,可让clone方法的参数与Foobar的copy参数完全一致:
interface Fizzbuzz { fun clone(id: Int = this.id, name: String = this.name, active: Boolean = this.active): Fizzbuzz } data class Foobar(val id: Int, val name: String, val active: Boolean = true) : Fizzbuzz { override fun clone(id: Int = this.id, name: String = this.name, active: Boolean = this.active): Foobar { return this.copy(id = id, name = name, active = active) } }
缺点是接口与具体实现强耦合,新增其他data class实现时需修改接口,扩展性差。
方案2:泛型+Lambda的通用方案(推荐)
通过泛型让接口与实现类绑定,用Lambda灵活修改属性,适配任意data class:
interface Fizzbuzz<T : Fizzbuzz<T>> { fun clone(block: T.() -> Unit): T } data class Foobar(val id: Int, val name: String, val active: Boolean = true) : Fizzbuzz<Foobar> { override fun clone(block: Foobar.() -> Unit): Foobar { return this.copy().apply(block) } }
调用时可像这样修改属性:
val original = Foobar(1, "test") val cloned = original.clone { name = "newTest" active = false }
这种方式既保留了类似copy的灵活修改能力,又让接口具备通用性,不同data class实现只需指定泛型类型即可。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

