Kotlin如何实现抽象类满足自定义结束日期规则的日期范围需求
问题1:当前实现合理性及优化方案
你的实现思路方向没问题,但存在一个属性不一致的隐藏bug:LocalDateRangeEndDate 子类自己持有构造传入的原始endDate值,而父类BaseLocalDateRange持有的是处理后的日期,你通过不同类型引用访问endDate会拿到不同结果,完全不符合业务预期。
可选优化方案如下:
- 用密封类替代普通抽象类,更适合这种只有固定两个子类的场景,编译器也能帮你做穷尽性检查
- 把endDate的处理逻辑放到子类的属性初始化位置,保证父子类属性值一致
import java.time.LocalDate // 用密封类限定只有两个子类 sealed class BaseLocalDateRange( open val startDate: LocalDate?, open val endDate: LocalDate? ) { // 把默认日期直接定义在父类里,所有子类都能复用 val DEFAULT_MAX_DATE: LocalDate = LocalDate.of(2099, 12, 31) } // 第一类:完全保留传入参数 data class LocalDateRange( override val startDate: LocalDate?, override val endDate: LocalDate? ) : BaseLocalDateRange(startDate, endDate) // 第二类:自动处理结束日期 data class LocalDateRangeWithDefaultEnd( override val startDate: LocalDate?, private val rawEndDate: LocalDate? // 原始传入的结束日期不要覆盖父类属性 ) : BaseLocalDateRange( startDate, // 处理逻辑写在这里,保证父类属性是处理后的值 if (rawEndDate == null || rawEndDate > DEFAULT_MAX_DATE) DEFAULT_MAX_DATE else rawEndDate )
如果不需要用到多态特性,完全没必要定义抽象类,直接用带工厂方法的单个数据类实现更简洁:
data class LocalDateRange( val startDate: LocalDate?, val endDate: LocalDate? ) { companion object { private val DEFAULT_MAX_DATE = LocalDate.of(2099, 12, 31) fun createWithEndLimit(startDate: LocalDate?, endDate: LocalDate?): LocalDateRange { val finalEnd = if (endDate == null || endDate > DEFAULT_MAX_DATE) DEFAULT_MAX_DATE else endDate return LocalDateRange(startDate, finalEnd) } } }
问题2:默认日期提取复用的实现方式
有三种常用的实现方式,可根据使用场景选择:
- 父类内定义常量:如果只有日期范围相关的类需要用这个默认值,就像上面密封类示例一样在
BaseLocalDateRange里定义属性,所有子类直接调用即可 - 伴生对象常量:如果这个默认值只在某一个子类/数据类里用,就定义在对应类的
companion object里,避免全局污染 - 顶层常量:如果整个项目多个模块都要用到这个默认日期,直接在kt文件顶层定义常量即可:
// 直接在kt文件顶部定义,全局可访问 val DEFAULT_MAX_DATE: LocalDate = LocalDate.of(2099, 12, 31)
内容的提问来源于stack exchange,提问作者Raftak
相关产品推荐
相关产品推荐

