Convertir des variables statiques de Java en Kotlin
j'essaie de convertir le code suivant en Kotlin et j'ai toujours l'une des classes (Foo) utilisées par Java. Quelle est la bonne façon de faire cette conversion?
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();
}
}
conversion Automatique fo Foo de 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)
}
Problème:
la classe Bar ne peut plus accéder à C_ID ou à des valeurs (erreur: "private access")
si je mets "const" devant C_ID, ça marche... mais je ne peux pas faire la même chose avec les valeurs ("const" peut Ne doit être utilisé que sur les primatifs ou String)
y a-t-il une autre façon de faire cela (pour que le code Java et le code Kotlin puissent accéder à tout dans Foo)?
4 réponses
la sémantique actuelle vient de Kotlin Bêta Candidat:
@JvmField et objets
nous avons fait la stratégie pour générer des champs purs (par opposition à
get
/set
paires) plus prévisible: désormais seules les propriétés annotées comme@JvmField
,lateinit
ouconst
sont exposés comme champs aux clients Java. Les versions plus anciennes utilisaient l'heuristique et créaient des champs statiques dans les objets inconditionnellement, ce qui est contre notre initiale objectif de conception d'avoir des API compatibles binaires par défaut.de plus, les instances singleton sont maintenant accessibles par le nom
INSTANCE
(au lieu deINSTANCE$
).
selon ceci et le référence, il y a trois façons de travailler avec les propriétés d'un Kotlin object
à partir de Java:
Utiliser
Foo.INSTANCE
.Par défaut, les propriétés de
object
ne seront pas des champs statiques pour Java, mais Java pouvez accéder aux propriétés parFoo
instance de l'objet --Foo.INSTANCE
.Donc l'expression
Foo.INSTANCE.getC_ID()
.Marquer une propriété avec
@JvmStatic
note:object Foo { @JvmStatic val C_ID = "ID" //... }
cela générera des getter statiques pour
C_ID
au lieu deFoo
instance getter qui sera accessible commeFoo.getC_ID()
.Utiliser
@JvmField
annotation sur la déclaration de la propriété:object Foo { @JvmField val C_ID = "ID" //... }
Cela va faire Kotlin compiler génère un champ statique pour Java au lieu de propriété. Puis, en Java, vous pouvez y accéder comme un champ statique:
Foo.C_ID
.mais il ne fonctionnera pas sur les propriétés sans les champs de soutien comme
all
dans ton exemple.
Pour les primitives, comme vous l'avez dit, on peut utiliser const
qui aura le même effet que @JvmField
en termes de visibilité en Java.
Par le chemin, quand il s'agit de méthodes, la situation est la même, et il est @JvmStatic
annotation pour eux.
dans votre classe foo vous pouvez placer ces propriétés et la méthode dans un objet compagnon:
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)
}
}
}
alors vous pouvez appeler Foo.getAll (), and Foo.C_ID, Foo.C_NAME et Foo.VALEUR.
Vous devriez être en mesure d'accéder aux valeurs "de la kotlin chemin":
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) }
}
Avec comme résultat:
ID
NAME
Process finished with exit code 0
c'est mieux si vous créez un nouveau fichier kotlin juste pour les constantes.
créer Constantes.kt fichier et collez code ci-dessous.
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)
}
dans votre activité principale, vous pouvez accéder aux constantes par le nom de la constante le studio android importera automatiquement les constantes. voici mon activité principale:
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)
}
}
}
j'ai réussi à obtenir la sortie log avec succès