在Kotlin初始值设定项中使用'this'-替代解决方案,还是可以忽略?

时间:2018-07-14 12:02:53

标签: constructor kotlin

我有一个使用事件服务将其注册为事件处理程序的类:

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进行自身注册,因为这是这种中间类型的要点。 >

我了解为什么这是一个问题-但我不确定如何推理解决问题的方法。

1 个答案:

答案 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方法,而不是构造函数。