Pourquoi utilisons-nous «objet compagnon» comme une sorte de remplacement des champs statiques Java dans Kotlin?

145

Quelle est la signification voulue de «objet compagnon»? Jusqu'à présent, je ne l'ai utilisé que pour remplacer Java staticlorsque j'en ai besoin.

Je suis confondu avec:

  • Pourquoi s'appelle-t-il "compagnon"?
  • Cela signifie-t-il que pour créer plusieurs propriétés statiques , je dois les regrouper dans un companion objectbloc?
  • Pour créer instantanément une instance de singleton étendue à une classe, j'écris souvent

:

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

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

Randy Sugianto 'Yuku'
la source

Réponses:

108
  • Quelle est la signification voulue de «objet compagnon»? Pourquoi s'appelle-t-il "compagnon"?

    Premièrement, Kotlin n'utilise pas le concept Java de staticmembres car Kotlin a son propre concept de objects pour décrire les propriétés et les fonctions liées à l'état singleton, et la staticpartie Java d'une classe peut être élégamment exprimée en termes de singleton: c'est un objet singleton qui peut être appelé par le nom de la classe. D'où la dénomination: c'est un objet qui vient avec une classe.

    Son nom était class objectetdefault object , mais il acompanion object ensuite été renommé, ce qui est plus clair et est également cohérent avec les objets compagnons Scala .

    Outre la dénomination, il est plus puissant que les staticmembres Java : il peut étendre des classes et des interfaces, et vous pouvez le référencer et le transmettre comme d'autres objets.

  • Cela signifie-t-il que pour créer plusieurs propriétés statiques, je dois les regrouper dans un companion objectbloc?

    Oui, c'est la manière idiomatique. Ou vous pouvez même les regrouper dans des objets non compagnons selon leur signification:

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

    Cela dépend de ce dont vous avez besoin dans chaque cas particulier. Votre code convient bien pour stocker un état lié à une classe qui est initialisée lors du premier appel.

    Si vous n'en avez pas besoin pour être connecté à une classe, utilisez simplement la déclaration d'objet:

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

    Vous pouvez également supprimer la lazy { ... }délégation pour que la propriété s'initialise lors de l'utilisation de la première classe, tout comme les initialiseurs statiques Java

    Vous pouvez également trouver des moyens utiles d' initialiser l'état singleton .

touche de raccourci
la source
Exemples sympas et idiomatiques.
Trein
19

Pourquoi s'appelle-t-il "compagnon"?

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

Cela signifie-t-il que pour créer plusieurs propriétés statiques, je dois les regrouper dans un bloc d'objets compagnon?

Oui. Chaque propriété / méthode "statique" doit être placée dans ce compagnon.

Pour créer instantanément une instance de singleton étendue à une classe, j'écris souvent

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

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

Allez plutôt avec object Singleton { }pour définir une classe singleton. Voir: Déclarations d'objets Vous n'avez pas besoin de créer une instance de Singleton, utilisez-la simplement comme çaSingleton.doWork()

Gardez simplement à l'esprit que Kotlin propose d'autres éléments pour organiser votre code. Il existe maintenant des alternatives aux fonctions statiques simples, par exemple vous pouvez utiliser des fonctions de niveau supérieur à la place.

D3xter
la source
7

Pourquoi s'appelle-t-il "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 n'utilisez que «objet» sans «compagnon», vous devez procéder comme suit:

val instance = MyClass.Factory.create()

Dans ma compréhension, «compagnon» signifie que cet objet est compagnon avec la classe extérieure.

Lyn
la source
"objet" sans "compagnon" est appelé ainsi (MyClass (). create ()). Comme un singleton, mais pour accéder à l'objet singleton, vous devez d'abord initialiser la classe "externe".
LiTTle
0

Nous pouvons dire que le compagnon est le même que "Static Block" comme Java, mais dans le cas de Kotlin, il n'y a pas de concept de bloc statique, alors le compagnon entre dans le cadre.

Comment définir un bloc compagnon:

class Example {
      companion object {
        fun display(){
        //place your code
     }
  }
}

Méthode d'appel du bloc compagnon, direct avec le nom de la classe

Example.Companion.display
Ankur Yadav
la source