Je veux connaître le moyen de créer une classe singleton, de sorte que ma classe Util ne instancie qu'une seule fois par application. Cependant, lorsque j'ai converti ma classe Java en kotlin, le code ci-dessous a été généré.
Est-ce correct?
companion object {
private var utilProject: UtilProject? = null
val instance: UtilProject
get() {
if (utilProject == null) utilProject = UtilProject()
return utilProject!!
}
}
Je pourrais trouver un connexe question, mais c'est avec paramètre, et je ne parviens pas à le convertir sans paramètres.
Juste
companion object {
val instance = UtilProject()
}
fera le travail car l'objet objet compagnon est lui-même un singleton au niveau de la langue.
(La instance
sera attribuée lorsque l'objet compagnon est premier appelé.)
-- Mis à jour --
Si vous devez ajuster le moment où l'objet singleton doit être initialisé, vous pouvez créer un objet pour chaque classe.
class UtilProject {
....
companion object {
val instance = UtilProject()
}
}
class AnotherClass {
...
companion object {
val instance = AnotherClass()
const val abc = "ABC"
}
}
fun main(args: Array<String>) {
val a = UtilProject.instance // UtilProject.instance will be initialized here.
val b = AnotherClass.abc // AnotherClass.instance will be initialized here because AnotherClass's companion object is instantiated.
val c = AnotherClass.instance
}
Ici, AnotherClass.instance
est initialisé avant que AnotherClass.instance
ne soit réellement appelé. Il est initialisé lorsque l'objet compagnon de AnotherClass
est appelé. Pour éviter d’être initialisé avant en cas de besoin, vous pouvez utiliser comme suit:
class UtilProject {
....
companion object {
fun f() = ...
}
}
class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}
object UtilProjectSingleton {
val instance = UtilProject()
}
object AnotherClassSingleton {
val instance = AnotherClass()
}
fun main(args: Array<String>) {
UtilProject.f()
println(AnotherClass.abc)
val a = UtilProjectSingleton.instance // UtilProjectSingleton.instance will be initialized here.
val b = AnotherClassSingleton.instance // AnotherClassSingleton.instance will be initialized here.
val c = UtilProjectSingleton.instance // c is a.
}
Si vous ne vous souciez pas de l'initialisation de chaque singleton, vous pouvez aussi utiliser ceci:
class UtilProject {
....
companion object {
fun f() = ...
}
}
class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}
object Singletons {
val utilProject = UtilProject()
val anotherClass = AnotherClass()
}
fun main(args: Array<String>) {
val a = Singletons.utilProject
val b = Singletons.anotherClass
}
En résumé,
an object
ou companion object
est un objet singleton en Kotlin.
Vous pouvez affecter des variables dans un objet ou objets, puis utiliser les variables comme si elles étaient des singletons.
object
ou companion object
est instancié lors de sa première utilisation. val
s et var
s dans un object
sont initialisés lorsque la object
est instanciée pour la première fois (c'est-à-dire lorsque la object
est utilisée pour la première fois).
Il existe un mot clé spécial object
pour les singletons dans Kotlin. Vous pouvez simplement taper quelque chose d'aussi simple que cela pour que votre classe de singleton fonctionne:
object MySingleton
ou quand vous voulez des fonctions membres:
object MySingleton {
fun someFunction(...) {...}
}
Et puis l'utiliser:
MySingleton.someFunction(...)
il y a une référence: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
EDIT:
Dans votre cas, il vous suffit de remplacer dans votre définition de class UtilProject
par ceci:
object UtilProject {
// here you put all member functions, values and variables
// that you need in your singleton Util class, for example:
val maxValue: Int = 100
fun compareInts(a: Int, b: Int): Int {...}
}
Et puis vous pouvez simplement utiliser votre singleton dans d'autres endroits:
UtilProject.compareInts(1, 2)
//or
var value = UtilProject.maxValue
Seul l'objet Word est nécessaire.
object UtilProject {
var bar: Int = 0
fun foo() {
}
}
Et vous accédez directement à l'objet qui n'a qu'une seule instance
fun main(args: Array<String>) {
UtilProject.bar = 1
println(UtilProject.bar)
}
Exemple simple paresseux:
companion object {
val instance: UtilProject by lazy { UtilProject() }
}
Dans Kotlin, vous devriez vous débarrasser de toute la notion de classe d’utilitaires singleton. La méthode idiomatique consiste simplement à déplacer toutes les déclarations au niveau supérieur.
Java:
public final class Util {
public static final Util UTIL = new Util();
private int prefixLength = 4;
private Util() {}
public void setPrefixLength(int newLen) {
prefixLength = newLen;
}
public String extractVin(String input) {
return input.substring(prefixLength);
}
}
Usage:
String vin = UTIL.extractVin("aoeuVN14134230430")
Dans Kotlin, créez simplement un fichier séparé appelé util.kt
avec les éléments suivants:
var prefixLength = 4
fun String.extractVin() = this.substring(prefixLength)
Usage:
val vin = "aoeuVN14134230430".extractVin()
Si votre Java intuition déclenche un drapeau rouge ici, rappelez-vous simplement que le package est la construction de l'espacement de noms et que, contrairement à Java, Kotlin ne regroupe pas les préoccupations relatives à l'espacement de noms et à l'encapsulation. Il n'y a pas de niveau d'accès "paquet privé", vous n'avez donc pas à décider que quelque chose doit rester dans le même paquet pour pouvoir être rendu paquet privé.
Ainsi, là où Java vous créez une classe dégénérée comme solution de contournement, dans Kotlin, vous créez simplement un fichier dans son propre paquet.
Un exemple Singleton
sur la modernisation pour prendre en charge l'appel de l'API.
object RetrofitClient {
private var instance: Api? = null
private val BASE_URL = "https://jsonplaceholder.typicode.com/"
fun getInstance(): Api? {
if (instance == null) {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
instance = retrofit.create(Api::class.Java)
}
return instance
}
}