web-dev-qa-db-fra.com

Singleton classe in Kotlin

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.

20
Khemraj

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. vals et vars 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).

22
Naetmul

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
32
dey

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)    
}
2
Gustavo Wilgenhoff

Exemple simple paresseux:

companion object {
    val instance: UtilProject by lazy { UtilProject() }
}
2
Michał Powłoka

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()

Mais ... vous polluez l'espace de noms de premier niveau!

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.

2
Marko Topolnik

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
    }
}
0
Abhishek Rana