这个引用在kotlin扩展属性的lazy初始值设定中

我正在尝试Kotlin,并希望为Activity实现一个惰性扩展属性:

/** * Activity module */ val Activity.activityModule: ActivityModule by lazy { ActivityModule(this) } 

编译器错误与:

 'this' is not defined in this context 

我如何能够将此作为“活动”? 我已阅读指南,但无法得到它。 this@Activity说参考是未解决的。

Kotlin中的lazy委托没有引用属性成员类。

我看到两个解决方案:

  1. 将其转换为扩展function
  2. 实施自己的委托

当第一次访问时, lazy调用initializer函数,然后存储initializer程序返回的值,以便在连续访问时返回该值。

Lazy一个实例能够存储恰好一个值。 当你将扩展属性委托给一个Lazy实例时,你会从接收者types的所有实例中得到一个Lazy服务的getValue请求的实例,在你的情况下它是Activity 。 这会导致只计算第一个“ Activity Lazy计算”值,并在其他所有“ Activity实例的后续调用中使用该值。

因此,虽然语法上可以将一个Activity作为接收者传递给初始值设定项,并将其引用为@voddan在本答案中的建议,但Lazy本身不能为不同的接收者存储不同的值。

具有扩展属性的外部存储的能力可能会被“附加属性”functionKT-7210覆盖。 我不认为Lazy应该有这个能力,因为它使其实施复杂化。

这里的其他答案指出,在stdlib的lazy接收器的当前实现中不可能引用它,并且可以实现它们自己的委托。 所以我决定实施它,并把它张贴在这里:

 class LazyWithReceiver(val initializer:This.()->Return) { private val values = WeakHashMap() @Suppress("UNCHECKED_CAST") operator fun getValue(thisRef:Any,property:KProperty<*>):Return = synchronized(values) { thisRef as This return values.getOrPut(thisRef) {thisRef.initializer()} } } 

这里有一些代码显示如何使用它。

这个实现使用一个弱哈希映射来为每个接收者存储一个单独的值…这带来了一些暗示……:

  • 结构相同的不同实例将具有相同的价值。

  • 在某些情况下,已经为某个接收者初始化的值可能被垃圾回收,这意味着如果再次访问初始值设定项,可能会再次调用初始值。

我认为没有办法从lazy的身体访问Activity ,至少用当前签名\执行: fun lazy(initializer: () -> T): Lazy

要做到这一点,签名必须看起来像

 fun  lazy(initializer: A.() -> T): Lazy2 

你可以自己实现这样一个扩展函数,或者用stdlib报告这个问题