new lateinit example data companion properties static field kotlin

properties - example - lateinit kotlin



Convertir variables estáticas de Java a Kotlin (4)

Estoy tratando de convertir el siguiente código a Kotlin Y aún tengo una de las clases (Foo) utilizadas por Java. ¿Cuál es la forma correcta de hacer esta conversión?

Java original:

public class Foo { public static final String C_ID = "ID"; public static final String C_NAME = "NAME"; public static final String[] VALUES = {"X", "Y", "Z"}; public static String[] getAll() { return new String[] {C_ID, C_NAME}; } } public class Bar { public void doStuff() { String var1 = Foo.C_ID; String[] array1 = Foo.VALUES; String[] array2 = Foo.getAll(); } }

Conversión automática de Foo a Kotlin

object Foo { val C_ID = "ID" val C_NAME = "NAME" val VALUES = arrayOf("X", "Y", "Z") val all: Array<String> get() = arrayOf(C_ID, C_NAME) }

Problema:

La clase de barra ya no puede acceder a C_ID o VALORES (error: "acceso privado")

Si pongo "const" delante de C_ID, funciona ... pero no puedo hacer lo mismo con VALUES ("const" solo se puede usar en primativos o cadena)

¿Hay alguna forma diferente de hacerlo (para que tanto el código Java como el código Kotlin puedan acceder a todo en Foo)?


Debes poder acceder a los valores "a la manera kotlin":

object Foo { val C_ID = "ID" val C_NAME = "NAME" val VALUES = arrayOf("X", "Y", "Z") val all: Array<String> get() = arrayOf(C_ID, C_NAME) } fun main(args: Array<String>) { Foo.all.forEach { it->println(it) } }

Con como resultado:

ID NAME Process finished with exit code 0


En tu clase foo puedes poner esas propiedades y el método dentro de un objeto compañero:

class Foo { companion object { val C_ID:String = "ID" val C_NAME:String = "NAME" @JvmField val VALUES = arrayOf("X", "Y", "Z") fun getAll():Array<String> { return arrayOf(C_ID, C_NAME) } } }

Luego puedes llamar a Foo.getAll () y Foo.C_ID, Foo.C_NAME y Foo.VALUES.


La semántica actual proviene de Kotlin Beta Candidate :

@JvmField y objetos

Hemos hecho que la estrategia para generar campos puros (en lugar de get / set pares) sea más predecible: de ahora en adelante, solo las propiedades anotadas como @JvmField , lateinit o const se exponen como campos para clientes Java. Las versiones anteriores usaban heurísticas y creaban campos estáticos en objetos de forma incondicional, lo que va en contra de nuestro objetivo de diseño inicial de tener API compatibles con compatibilidad binaria de forma predeterminada.

Además, ahora se puede acceder a las instancias singleton con el nombre INSTANCE (en lugar de INSTANCE$ ).

De acuerdo con esto y con la reference , hay tres formas de trabajar con las propiedades de un object Kotlin desde Java:

  • Utilice Foo.INSTANCE .

    De forma predeterminada, las propiedades del object no serán campos estáticos para Java, pero Java puede acceder a las propiedades a través de la instancia del objeto Foo - Foo.INSTANCE .

    Así que la expresión será Foo.INSTANCE.getC_ID() .

  • Marque una propiedad con la anotación @JvmStatic :

    object Foo { @JvmStatic val C_ID = "ID" //... }

    Esto generará un captador estático para C_ID lugar del captador de instancias de Foo que se podrá acceder como Foo.getC_ID() .

  • Utilice la anotación @JvmField en la declaración de propiedad:

    object Foo { @JvmField val C_ID = "ID" //... }

    Esto hará que el compilador Kotlin genere un campo estático para Java en lugar de propiedad. Luego, en Java puedes acceder a él como un campo estático: Foo.C_ID .

    Pero no funcionará en propiedades sin respaldar campos como all en su ejemplo.

Para los primitivos, como dijiste, puedes usar const que tendrá el mismo efecto que @JvmField en términos de visibilidad en Java.

Por cierto, cuando se trata de métodos, la situación es la misma, y ​​hay @JvmStatic anotación @JvmStatic para ellos.


es mejor si creas un nuevo archivo kotlin solo para constantes.

crear el archivo Constants.kt y pegar debajo del código.

object Constants { val C_ID = "ID" val C_NAME = "NAME" val VALUES = arrayOf("X", "Y", "Z") val all: Array<String> get() = arrayOf(C_ID, C_NAME) }

en su actividad principal, puede acceder a las constantes por el nombre de constante que Android Studio importará automáticamente. Aquí está mi actividad principal:

import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import com.example.architecturecompintro.Constants.C_ID import com.example.architecturecompintro.Constants.C_NAME import com.example.architecturecompintro.Constants.VALUES import com.example.architecturecompintro.Constants.all class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val TAG = "info" Log.i(TAG, C_ID) Log.i(TAG,C_NAME) for(item in VALUES) { Log.i(TAG,item) } val arrayItem = all for(item in arrayItem) { Log.i(TAG,item) } } }

Pude obtener resultados de registro con éxito