Kotlin: Inicializa el atributo de class en el constructor

Creo una class Kotlin con un atributo de class, que quiero inicializar en el constructor:

public class TestClass { private var context : Context? = null // Nullable attribute public constructor(context : Context) { this.context = context } public fun doSomeVoodoo() { val text : String = context!!.getString(R.string.abc_action_bar_home_description) } } 

Desafortunadamente tengo que declarar el atributo como Nullable con el "?" signo, aunque el atributo se inicializará en el constructor. Declarar este atributo como atributo Nullable hace que siempre sea necesario forzar un valor no nulo con "!! o para proporcionar un cheque nulo con "?".

¿Hay alguna forma de evitar esto, si el atributo de class se inicializará en el constructor? Me gustaría apreciar una solución como esta:

 public class TestClass { private var context : Context // Non-Nullable attribute public constructor(context : Context) { this.context = context } public fun doSomeVoodoo() { val text : String = context.getString(R.string.abc_action_bar_home_description) } } 

Si lo único que estás haciendo en el constructor es una asignación, entonces podrías usar el Constructor Primario con una Propiedad privada.

p.ej:

 public class TestClass(private var context: Context) { public fun doSomeVoodoo() { val text = context.getString(R.string.abc_...) } } 

Como muestra D3xter, tiene la opción de configurarlo en el constructor. También tienes otras opciones. Aquí todos ellos son …

Cree la propiedad dentro del constructor (según @D3xter), este es el caso más común para las properties simples inicializadas directamente por el constructor primario :

 class TestClass(private val context: Context) { fun doSomeVoodoo() { val text : String = context.getString() } } 

Puede declarar la propiedad val y no inicializarla, suponiendo que todos los constructores posibles la inicialicen (según su segundo ejemplo en la pregunta). Esto es normal cuando tienes más de un constructor que podría inicializar un valor de manera diferente :

 public class TestClass { private val context: Context public constructor(context : Context) { this.context = context } // alternative constructor public constructor(pre: PreContext) { this.context = pre.readContext() } public fun doSomeVoodoo() { val text : String = context.getString() } } 

Puede pasar parameters de constructor que no son declaraciones de propiedad y luego usarlos dentro de las inicializaciones de properties. Esto es común cuando tiene inicializaciones más complejas o necesita usar properties delegadas :

 class TestClass(context: PreContext) { private val context : Context by lazy { context.readContext() } private val other: List<Items> = run { context.items.map { it.tag }.filterNotNull() } private val simpleThing = context.getSimple() fun doSomeVoodoo() { val text : String = context.getString() } } 

Usar el modificador de lateinit hora cuando no puede inicializar el valor durante la construcción, pero está seguro de que se realizará antes de su primer acceso de lectura. Esto es común cuando una dependency injection, un contenedor IoC o algo crea una versión vacía de su class y luego la inicializa de inmediato :

 class TestClass() { private lateinit var context : Context // set by something else after construction fun doSomeVoodoo() { val text : String = context.getString() } } 

Para lateinit la propiedad debe ser actualmente una var y no funciona con types primitivos.

También puede declarar una propiedad var y no inicializarla si usa un delegado diseñado para tal fin, como Delegates.notNull() . Esto es similar a lateinit y común cuando quiere una var que no tiene un estado inicial, pero se establece más tarde después de la construcción en un punto desconocido en el time :

 public class TestClass() { private var context: Context by Delegates.notNull() public fun doSomeVoodoo() { // if context is not set before this is called, an exception is thrown val text : String = context.getString() } } 
  • Interoperabilidad de Java: aplique @JvmName a los buscadores de properties en la class de interfaz o abstracta
  • Enumeraciones efectivas en Kotlin con búsqueda inversa
  • Forma correcta de usar genérico reificado en Kotlin
  • Centrar verticalmente una VideoView en el retrato
  • Inferencia de tipo Observable.combineLatest en kotlin
  • DuplicateFileException en la compilation de apk usando Kotlin
  • firebase db: models con properties delegadas de Kotlin
  • Configuración de security de spring de Kotlin
  • Cómo usar la biblioteca kmongo para operador de sector
  • Asignación de properties a un object javascript utilizando nombres de properties dinámicas
  • TextColor está cambiando a uno incorrecto