Tengo una clase O y una clase anidada dentro de O llamada N
En una función de N , quiero hacer referencia a this de O usando this@O .
Pero no reconoce O , solo cuando uso inner class .
Sin embargo, si uso clases internas, android-studio sugiere que esto podría generar fugas.
¿Hay otra forma de hacer referencia a la clase externa o evitar fugas?
La posibilidad de pérdida de memoria se debe al hecho de que cada instancia de una clase inner contiene una referencia a una instancia de la clase externa. Es posible que la lógica del programa no necesite esa instancia de clase externa, pero aún está visible y, por lo tanto, no está sujeta a la recolección de elementos no utilizados.
Por lo tanto, si sabe que es posible que la instancia de la clase anidada no necesite todo el contenido de la instancia de la clase externa para su lógica, puede asegurarse de que no haya pérdidas de memoria si no usa las clases inner .
Si aún necesita algunas partes de la instancia de la clase externa, puede pasar esos valores a la instancia de la clase anidada manualmente:
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) }Si también necesita la instancia de la clase anidada para observar los cambios de la propiedad de la instancia de la clase externa (no solo usando una instantánea de la propiedad en el momento de la construcción de la instancia de la clase anidada), puede envolver manualmente esa propiedad en un contenedor de referencia y pasar ese contenedor al constructor de clases anidadas:
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) } En lugar de la clase CHolder , es posible que desee utilizar alguna solución genérica si este patrón se repite en su código; esto es solo una demostración.
Luego, si desea hacer referencia a la instancia completa de la clase externa, todavía hay una opción para pasarla al constructor de la clase anidada. En comparación con inner class , esto le permite controlar manualmente la vida útil de la instancia externa y descartar la referencia a ella una vez que no sea necesaria:
class A { class D(private var outer: A?) { fun forgetOuterInstance() { outer = null } } fun createD(): D = D(this) } Y finalmente, si su clase anidada necesita la instancia de la clase externa durante toda su vida útil, o si la clase externa no tiene recursos costosos y puede lidiar con la vida útil potencialmente más larga de sus instancias, entonces está bien usar una inner class , solo tenga en cuenta que la instancia de la clase externa permanecerá activa mientras lo haga la instancia de la clase interna. Debido a esto, es posible que desee mover algunos recursos fuera de la clase externa para retenerlos y liberarlos de una forma más granular.