如何在Kotlin伴生对象中访问构造器参数timeZoneId
解决Singleton类伴生对象访问实例依赖的问题
你当前代码报错的核心原因是:伴生对象属于类本身,而非类的实例,它无法直接访问ChInteractor实例持有的timeZoneId参数——这个参数是注入给实例的成员变量,伴生对象没有权限直接调用。
下面是几种可行的解决方案:
方案一:将方法改为实例方法(推荐)
既然timeZoneId是实例的依赖,把getNextSessionDateText从伴生对象移到类的成员方法里,就能直接访问timeZoneId了。因为ChInteractor是Singleton,整个应用只有一个实例,调用时直接用注入的实例调用即可,这也是最符合依赖注入设计的方式。
修改后的代码:
@Singleton class ChInteractor @Inject constructor( val timeZoneId: ZoneId ) { fun getNextSessionDateText( clock: Clock, targetDaySeconds: Int ): String { val date = LocalDateTime.now(clock) val nowDaySeconds = date.toLocalTime().toSecondOfDay() val newPastSeconds = nowToMidnightSeconds(timeZoneId) + targetDaySeconds return "something" } companion object { private val simpleDateFormat = SimpleDateFormat("EEEE dd MMM") const val HOUR_SECONDS = 3600 const val MINUTE_SECONDS = 60 } // 补充你需要的nowToMidnightSeconds方法实现 private fun nowToMidnightSeconds(timeZoneId: ZoneId): Int { // 你的业务逻辑 return 0 } }
方案二:给伴生对象方法添加timeZoneId参数
如果一定要保留伴生对象的方法,可以把timeZoneId作为参数传入方法,调用时从ChInteractor的实例中获取并传递。
修改后的代码:
@Singleton class ChInteractor @Inject constructor( val timeZoneId: ZoneId ) { companion object { fun getNextSessionDateText( clock: Clock, targetDaySeconds: Int, timeZoneId: ZoneId // 新增参数 ): String { val date = LocalDateTime.now(clock) val nowDaySeconds = date.toLocalTime().toSecondOfDay() val newPastSeconds = nowToMidnightSeconds(timeZoneId) + targetDaySeconds return "something" } private val simpleDateFormat = SimpleDateFormat("EEEE dd MMM") const val HOUR_SECONDS = 3600 const val MINUTE_SECONDS = 60 private fun nowToMidnightSeconds(timeZoneId: ZoneId): Int { // 你的业务逻辑 return 0 } } } // 调用方式(使用注入的ChInteractor实例) chInteractor.getNextSessionDateText(clock, targetDaySeconds, chInteractor.timeZoneId)
方案三:将ZoneId作为Singleton注入并在伴生对象中获取(不推荐)
如果你的DI框架(比如Dagger)支持,可以把ZoneId也标记为Singleton,然后在伴生对象中通过DI框架直接获取。但这种方式会让伴生对象和DI框架强耦合,不利于代码的可测试性和独立性,因此不推荐。
示例(以Dagger为例):
// 先在DI模块中提供Singleton的ZoneId @Module class AppModule { @Provides @Singleton fun provideZoneId(): ZoneId { return ZoneId.systemDefault() // 或你的自定义时区 } } // 修改ChInteractor @Singleton class ChInteractor @Inject constructor( val timeZoneId: ZoneId ) { companion object { // 假设你能静态获取Dagger组件实例 private val timeZoneId get() = DaggerAppComponent.create().provideZoneId() fun getNextSessionDateText( clock: Clock, targetDaySeconds: Int ): String { val date = LocalDateTime.now(clock) val nowDaySeconds = date.toLocalTime().toSecondOfDay() val newPastSeconds = nowToMidnightSeconds(timeZoneId) + targetDaySeconds return "something" } private val simpleDateFormat = SimpleDateFormat("EEEE dd MMM") const val HOUR_SECONDS = 3600 const val MINUTE_SECONDS = 60 private fun nowToMidnightSeconds(timeZoneId: ZoneId): Int { // 你的业务逻辑 return 0 } } }
内容的提问来源于stack exchange,提问作者BRDroid
相关产品推荐
相关产品推荐

