我有一个使用事件服务将其注册为事件处理程序的类:
interface CommunicationService {
fun sendActivationMessage(toEmail: String)
}
abstract class EventCommunicationService : CommunicationService, AbstractEventHandler {
constructor(eventService: EventService) {
eventService.registerListener(this)
}
override fun onEvent(event: Event) {
if (event.type == EventType.USER_CREATED) {
sendActivationMessage(event.userEmail)
}
}
}
存在的想法可以是EmailCommunicationService
,也可以是模拟的测试版本,等等,这些都不需要在创建用户时就将自己注册为侦听器。
但是Kotlin抱怨我是
在非最终类EventCommunicationService的构造函数中泄漏“ this”
我是哪个。我很容易忽略警告-但是有更好的方法吗?
我已经尝试使用init { }
块而不是构造函数,但是警告是相同的。
我基本上想要一个“构造后”回调或类似的回调,该回调或类似回调可用于使该服务向构造函数中提供的EventService进行自身注册,因为这是这种中间类型的要点。 >
我了解为什么这是一个问题-但我不确定如何推理解决问题的方法。
答案 0 :(得分:1)
init
块实际上是构造函数的一部分(使用JVM术语),因此这对解决问题没有帮助。一般而言,完全不安全是不安全的:出于某些原因,请参见Leaking this in constructor warning(只是忽略已接受的答案,其注释包含真实内容,伊什塔尔的答案也是如此)。
一个选项(假设所有子类都具有无参数构造函数,尽管可以扩展):
abstract class <T : EventCommunicationService> EventCommunicationServiceCompanion(private val creator: () -> T) {
operator fun invoke(eventService: EventService): T {
val obj = creator()
eventService.registerListener(obj)
return obj
}
}
// a subclass of EventCommunicationService:
class MyService private constructor () : EventCommunicationService {
companion object : EventCommunicationServiceCompanion<MyService>(MyService::new)
}
要创建MyService
,您仍然可以调用MyService(eventService)
,但这实际上是伴随对象的invoke
方法,而不是构造函数。