如何在Kotlin中复用已有DTO类创建联合类型?
在Kotlin中复用已有DTO实现联合类型的方案
Kotlin目前没有原生支持像FooDto | BarDto这样的联合类型语法,但可以通过以下几种方式复用已有DTO实现类似效果:
1. 密封类包装器(推荐,封闭性强)
不需要修改原有FooDto和BarDto,用密封类做一层轻量包装,既保留原有类的复用性,又实现封闭的联合类型:
// 定义密封类作为联合类型的容器 sealed class FooOrBar { // 用data class包装已有DTO,自动继承密封类 data class FooWrapper(val dto: FooDto) : FooOrBar() data class BarWrapper(val dto: BarDto) : FooOrBar() } // 定义AnotherDto时使用密封类作为属性类型 class AnotherDto( val e: FooOrBar )
使用时通过when表达式处理,编译器会强制检查所有分支(因为密封类的子类是确定的),避免遗漏:
fun processE(e: FooOrBar) { when(e) { is FooOrBar.FooWrapper -> { // 直接访问原有FooDto的属性 println("FooDto的a属性:${e.dto.a}") } is FooOrBar.BarWrapper -> { println("BarDto的c属性:${e.dto.c}") } } }
2. 标记接口(适合允许修改原有DTO的场景)
如果可以修改FooDto和BarDto的代码,定义一个空接口作为标记,让两个DTO实现该接口,之后就可以用接口作为联合类型:
// 空标记接口 interface FooOrBarMarker // 修改原有DTO实现接口 class FooDto( val a: String, val b: Double, ) : FooOrBarMarker class BarDto( val c: String, val d: String, ) : FooOrBarMarker // AnotherDto的属性类型为标记接口 class AnotherDto( val e: FooOrBarMarker )
这种方式更简洁,但缺点是接口是开放的——其他类也可以实现FooOrBarMarker,破坏了“仅FooDto或BarDto”的约束。处理时同样可以用when,但编译器不会强制穷尽分支。
3. 使用Kotlin的typealias(仅用于简化类型,无约束性)
如果只是想简化类型名称,但不需要编译时约束,可以用类型别名,但这只是语法糖,无法限制只能传入FooDto或BarDto:
typealias FooOrBar = Any class AnotherDto( val e: FooOrBar )
这种方式不推荐,因为完全没有类型安全保障,仅适合临时简化代码的场景。
内容的提问来源于stack exchange,提问作者four-eyes
相关产品推荐
相关产品推荐

