Kotlin中如何对共享相同变量的自定义对象执行相同操作?
Kotlin sealed class多子类公共属性处理方案
你遇到的是Kotlin智能转型的限制:多类型联合匹配的分支不会自动提取不同类型的同名公共属性,以下是几种可落地的优化方案:
方案1:抽取公共接口(最推荐,结构最合理)
先定义包含公共属性的接口,让带直接timestamp的子类实现该接口:
interface TimestampHolder { var timestamp: String? } sealed class Example { // 注:原示例类名不符合Kotlin命名规范,统一调整为首字母大写 data class Foo1(override var timestamp: String?, var model1: Model1?): Example(), TimestampHolder data class Foo2(override var timestamp: String?, var model2: Model2?): Example(), TimestampHolder data class Foo3(var model3: Model3?): Example() }
调整后业务代码可以直接简化为:
when(foo) { is TimestampHolder -> foo.timestamp = ts is Foo3 -> foo.model3.timestamp = ts }
后续新增同类型带timestamp的子类只要实现TimestampHolder接口即可,无需修改现有业务分支,可扩展性最强。
方案2:扩展属性兼容现有结构
如果不想改动原有sealed class的定义,可以通过扩展属性统一封装timestamp的读写逻辑:
var Example.timestamp: String? get() = when(this) { is Example.Foo1 -> timestamp is Example.Foo2 -> timestamp is Example.Foo3 -> model3?.timestamp } set(value) { when(this) { is Example.Foo1 -> timestamp = value is Example.Foo2 -> timestamp = value is Example.Foo3 -> model3?.timestamp = value } }
封装后业务逻辑可以直接一行实现,完全不需要分支判断:
foo.timestamp = ts
如果后续不同类型的赋值逻辑有调整,只需要修改扩展属性的setter即可,上层调用无需改动。
方案3:无结构改动的临时写法
如果只是临时需求不想调整现有结构,也可以在联合分支中手动强转实现:
when(foo) { is Example.Foo1, is Example.Foo2 -> { (foo as TimestampHolder).timestamp = ts } is Example.Foo3 -> foo.model3.timestamp = ts }
该方案不建议长期使用,后续新增子类时仍需要修改分支,维护成本较高。
内容的提问来源于stack exchange,提问作者misfit
相关产品推荐
相关产品推荐

