Pourquoi utilisons-nous" companion object " comme une sorte de remplacement pour les champs statiques Java à Kotlin?

Quel est le sens de "compagnon de l'objet"? Jusqu'à présent, je l'ai utilisé pour remplacer Java static quand j'en ai besoin.

je suis confondu avec:

  • pourquoi s'appelle-t-on"compagnon"?
  • signifie-t-il que pour créer plusieurs propriétés statiques , je dois les regrouper à l'intérieur du bloc companion object ?
  • pour créer instantanément une instance singleton qui est scoped à une classe, j'écris souvent

:

companion object {
    val singleton by lazy { ... }
}

ce qui semble être une façon unidiomatique de le faire. Quelle est la meilleure façon de faire?

109
demandé sur Maddy 2016-07-14 21:35:04

3 réponses

  • Quel est le sens de "compagnon de l'objet"? Pourquoi ça s'appelle "compagnon"?

    tout D'abord, Kotlin n'utilise pas le concept Java des membres static parce que Kotlin a son propre concept de object s pour décrire les propriétés et les fonctions liées à l'état singleton, et Java static partie d'une classe peut être exprimée élégamment en termes de singleton: c'est un objet unique qui peut être appelé par le nom de la classe. D'où le nom: c'est un objet qui vient avec une classe.

    son nom était class object et default object , mais ensuite il a été renommé en companion object ce qui est plus clair et est également compatible avec Scala companion objects .

    en plus de nommer, il est plus puissant que Java static membres: il peut étendre les classes et les interfaces, et vous pouvez le référencer et le transmettre comme les autres objets.

  • signifie-t-il que pour créer plusieurs propriétés statiques, je dois les regrouper à l'intérieur du bloc companion object ?

    Oui, c'est la façon idiomatique. Ou vous pouvez même les regrouper dans des objets non-companions par leur sens:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
    
  • pour créer instantanément une instance singleton qui est scopée à une classe, j'écris souvent /*...*/ qui semble être une façon unidiomatique de le faire. Quelle est la meilleure façon de faire?

    cela dépend de ce dont vous avez besoin dans chaque cas particulier. Votre code convient bien pour stocker l'état lié à une classe qui est initialisée dès le premier appel.

    si vous n'avez pas besoin d'être connecté à une classe, utilisez simplement object déclaration:

    object Foo {
        val something by lazy { ... }
    }
    

    vous pouvez également supprimer lazy { ... } délégation pour rendre la propriété initialiser sur l'usage de première classe, tout comme Java static initialisers

    vous pourriez également trouver des moyens utiles de initialisant l'état singleton .

79
répondu hotkey 2017-11-15 11:22:39

pourquoi s'appelle-t-on "compagnon"?

Cet objet est un compagnon des instances. IIRC il y a eu une longue discussion ici: à venir-changement-classe-objets-repensée

signifie-t-il que pour créer des propriétés statiques multiples, je dois les regrouper à l'intérieur du bloc d'objets compagnon?

Oui. Chaque propriété/méthode" statique " doit être placé à l'intérieur de ce compagnon.

pour créer instantanément une instance singleton qui est scoped à une classe, j'écris souvent

vous ne créez pas l'instance singleton instantanément. Il est créé lors de l'accès singleton pour la première fois.

ce qui semble être une façon unidiomatique de le faire. Quelle est la meilleure façon de faire?

plutôt aller avec object Singleton { } pour définir un singleton de classe. Voir: Déclarations D'Objet Vous n'avez pas à créer une instance de Singleton , il suffit de l'utiliser comme cela Singleton.doWork()

il suffit de garder à l'esprit que Kotlin offre d'autres choses pour organiser votre code. Il existe maintenant des alternatives aux fonctions statiques simples, par exemple vous pouvez utiliser des fonctions de haut niveau à la place.

14
répondu D3xter 2016-07-14 19:06:34

pourquoi s'appelle-t-on "compagnon"?

une déclaration d'objet à l'intérieur d'une classe peut être marquée avec le mot-clé compagnon:

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

les membres de l'objet compagnon peuvent être appelés en utilisant simplement le nom de classe comme qualificatif:

val instance = MyClass.create()

si vous utilisez seulement "objet" sans "compagnon", vous devez faire comme ceci:

val instance = MyClass.Factory.create()

d'après ce que j'ai compris, "compagnon" signifie que cet objet est compagnon avec le outter classe.

4
répondu Lyn 2018-01-17 01:33:51