99 votes

Classe singleton en Kotlin

Je veux savoir comment créer une classe singleton en Kotlin, afin que ma classe Util ne l'instancie qu'une seule fois par exécution de l'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 lien question mais c'est avec des paramètres, et je n'arrive pas à le convertir sans paramètres.

112voto

dey Points 946

Il existe un mot-clé spécial object pour les singletons en Kotlin. Vous pouvez taper quelque chose d'aussi simple que ceci pour obtenir une classe singleton fonctionnelle :

object MySingleton

ou quand vous voulez des fonctions membres :

object MySingleton {
    fun someFunction(...) {...}
}

Et ensuite l'utiliser :

MySingleton.someFunction(...)

il y a une référence : https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations

EDITAR:

Dans votre cas, vous devez simplement remplacer dans votre définition de class UtilProject à ça :

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 ensuite, vous pouvez simplement utiliser votre singleton à d'autres endroits :

UtilProject.compareInts(1, 2)
//or
var value = UtilProject.maxValue

89voto

Naetmul Points 6394

Juste

companion object {
    val instance = UtilProject()
} 

fera l'affaire car le objet compagnon est lui-même un singleton de niveau langue.
(Le instance sera créé lorsque l'objet compagnon sera premièrement appelé.)

-- Mis à jour --

Si vous devez contrôler le moment où l'objet singleton est 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 AnotherClass.instance est effectivement appelé. Il est initialisé lorsque AnotherClass L'objet compagnon de l'utilisateur est appelé. Pour éviter qu'il soit initialisé avant le moment où il est nécessaire, vous pouvez utiliser comme ceci :

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 du moment où chaque singleton est initialisé, vous pouvez aussi l'utiliser comme 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é,
un object ou un companion object est un objet singleton en Kotlin.
Vous pouvez affecter des variables dans un objet o objets et ensuite utiliser les variables comme s'il s'agissait de singletons.

object o companion object est instancié lors de sa première utilisation. val et var dans un object sont initialisés lorsque le object est instancié pour la première fois (c'est-à-dire lorsque l'élément object est utilisé pour la première fois).

14voto

Michał Powłoka Points 364

Un exemple de paresseux très simple :

companion object {
    val instance: UtilProject by lazy { UtilProject() }
}

5 votes

Pas besoin ! utilisez simplement le mot clé object

0 votes

Vrai. En fait, le mot-clé objet fait la même chose

8voto

Seul le mot objet 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)    
}

3voto

Marko Topolnik Points 77257

En Kotlin, vous devriez vous débarrasser de toute la notion de classe singleton utilitaire. La méthode idiomatique consiste à déplacer simplement 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);
    }
}

Utilisation :

String vin = UTIL.extractVin("aoeuVN14134230430")

En Kotlin, il suffit de créer un fichier séparé appelé util.kt avec les éléments suivants :

var prefixLength = 4

fun String.extractVin() = this.substring(prefixLength)

Utilisation :

val vin = "aoeuVN14134230430".extractVin()

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

Si votre intuition Java déclenche un drapeau rouge ici, rappelez-vous simplement que la paquet est la construction de l'espacement des noms et, contrairement à Java, Kotlin ne confond pas les préoccupations de l'espacement des noms et de l'encapsulation. Il n'y a pas de niveau d'accès "package-private", vous n'avez donc pas à décider que quelque chose doit rester dans le même package pour pouvoir être rendu package-private.

Ainsi, alors qu'en Java vous créez une classe dégénérée comme solution de rechange, en Kotlin vous créez simplement un fichier dans son propre paquet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X