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
oconst
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 deINSTANCE$
).
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 objetoFoo
-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 deFoo
que se podrá acceder comoFoo.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