Kotlin ссылочный внешний класс из вложенного класса - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть класс O и вложенный класс внутри O с именем N.

В функции N я хочу сослаться на this из O с помощьюthis@O.

Но он не распознает O, только когда я использую inner class.

Однако, если я использую внутренние классы, android-studio предполагает, что это может привести к утечкам.

Есть ли другой способ ссылаться на внешний класс или избегать утечек?

1 Ответ

0 голосов
/ 28 февраля 2019

Возможность утечки памяти вызвана тем фактом, что каждый экземпляр класса inner содержит ссылку на экземпляр внешнего класса.Этот экземпляр внешнего класса может не понадобиться логике программы, но он все еще видим и, следовательно, не подлежит сборке мусора.

Итак, если вы знаете, что экземпляр вложенного классаможет не потребоваться все содержимое экземпляра внешнего класса для его логики, вы можете убедиться в отсутствии утечек памяти, не используя inner классы.

Если вам все еще нужны некоторые части экземпляра внешнего класса, выможно передать эти значения экземпляру вложенного класса вручную:

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)
}

Если вам также нужен экземпляр вложенного класса, чтобы наблюдать изменения свойства экземпляра внешнего класса (а не просто использовать моментальный снимок свойства во вложенном классе).время создания экземпляра класса), вы можете вручную обернуть это свойство в держатель ссылки и передать его в конструктор вложенного класса:

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)
}

Вместо класса CHolder может потребоватьсяиспользуйте какое-то общее решение, если этот шаблон повторяется в вашем коде;это всего лишь демонстрация.

Тогда, если вы хотите сослаться на весь экземпляр внешнего класса, есть возможность передать его конструктору вложенного класса.По сравнению с inner class это позволяет вам вручную управлять временем жизни внешнего экземпляра и удалять ссылку на него, когда он не нужен:

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

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

И, наконец, если вашему вложенному классу нужен внешний классэкземпляра в течение всего времени его существования, или если внешний класс не содержит дорогих ресурсов, и вы можете иметь дело с потенциально более длинным временем жизни его экземпляров, тогда можно использовать inner class, просто имейте в виду, что экземпляр внешнего классаостанется в живых до тех пор, пока это делает экземпляр внутреннего класса.В связи с этим вы можете захотеть переместить некоторые ресурсы из внешнего класса для хранения и выпустить их более детально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...