简体   繁体   English

Kotlin 从嵌套类引用外部类

[英]Kotlin reference outer class from nested class

I have a class O and a nested class inside of O called N .我有一个O类和O内部的一个嵌套类,称为N

In a function of N I want to reference this of O by using this@O .在的功能N我要引用thisO通过使用this@O

But it does not recognize O , only when I use inner class .但它不识别O ,只有当我使用inner class

However, if I use inner classes, android-studio suggests that this might lead to leaks.但是,如果我使用内部类,android-studio 建议这可能会导致泄漏。

Is there another way to reference the outer class or avoid leaks?是否有另一种方法来引用外部类或避免泄漏?

The memory leak possibility is caused by the fact that each instance of an inner class holds a reference to an instance of the outer class.内存泄漏的可能性是由于inner类的每个实例都持有对外部类实例的引用。 That outer class instance may not be needed by the program logic, but it is still visible and thus is not subject to garbage collection.程序逻辑可能不需要该外部类实例,但它仍然可见,因此不受垃圾回收的影响。

So, if you are aware that the nested class instance may not need the whole content of the outer class instance for its logic, you can ensure that there's no memory leaks by not using inner classes.因此,如果您知道嵌套类实例的逻辑可能不需要外部类实例的全部内容,则可以通过不使用inner类来确保没有内存泄漏。

If you still need some parts of the outer class instance, you can pass those values to the nested class instance manually:如果您仍然需要外部类实例的某些部分,您可以手动将这些值传递给嵌套类实例:

class A {
    val b: B = someB()
    val c: C = someC()

    // D uses C but does not need B, so we pass C to the constructor:
    class D(private val c: C) { /* ... */ }

    fun createD(): D = D(c)
}

If you also need the nested class instance to observe the changes of the outer class instance property (not just using a snapshot of the property at the nested class instance construction time), you may manually wrap that property into a reference holder and pass that holder to the nested class constructor:如果您还需要嵌套类实例来观察外部类实例属性的变化(不仅仅是在嵌套类实例构建时使用属性的快照),您可以手动将该属性包装到引用持有者中并传递该持有者到嵌套类构造函数:

class A {
    val b: B = someB()

    private val cHolder = CHolder(someC())

    class CHolder(var c: C)

    var c: C
        get() = cHolder.c
        set(value) { cHolder.c = value }

    // D uses C but does not need B, so we pass C to the constructor:
    class D(private val cHolder: CHolder) { /* ... */ }

    fun createD(): D = D(cHolder)
}

Instead of the class CHolder , you may want to use some generic solution if this pattern repeats in your code;如果此模式在您的代码中重复,您可能希望使用一些通用解决方案而不是类CHolder this is just a demo.这只是一个演示。

Then, if you want to reference the whole instance of the outer class, there's still an option to pass it to the nested class constructor.然后,如果您想引用外部类的整个实例,仍然可以选择将其传递给嵌套类构造函数。 Compared to inner class , this allows you to manually control the lifetime of the outer instance and drop the reference to it once it is not needed:inner class相比,这允许您手动控制外部实例的生命周期,并在不需要时删除对它的引用:

class A {
    class D(private var outer: A?) {
        fun forgetOuterInstance() {
            outer = null
        }
    }

    fun createD(): D = D(this)
}

And finally, if your nested class needs the outer class instance during all of its lifetime, or if the outer class does not hold any expensive resources and you can deal with the potentially longer lifetime of its instances, then it's OK to use an inner class , just keep in mind that the outer class instance will stay alive as long is the inner class instance does.最后,如果您的嵌套类在其整个生命周期中都需要外部类实例,或者如果外部类不持有任何昂贵的资源并且您可以处理其实例可能更长的生命周期,那么可以使用inner class ,请记住,只要内部类实例存在,外部类实例就会保持活动状态。 Due to this, you may want to move some resources out of the outer class to hold and release them in a more granular way.因此,您可能希望将一些资源移出外部类,以更精细的方式保留和释放它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM