¿Por qué usamos "objeto complementario" como una especie de reemplazo para los campos estáticos de Java en Kotlin?

145

¿Cuál es el significado pretendido de "objeto compañero"? Hasta ahora lo he estado usando solo para reemplazar Java staticcuando lo necesito.

Estoy confundido con:

  • ¿Por qué se llama "compañero"?
  • ¿Significa que para crear múltiples propiedades estáticas , tengo que agruparlo dentro del companion objectbloque?
  • Para crear instantáneamente una instancia de singleton que tenga el alcance de una clase, a menudo escribo

:

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

lo que parece una forma unidiomática de hacerlo. ¿Cuál es la mejor manera?

Randy Sugianto 'Yuku'
fuente

Respuestas:

108
  • ¿Cuál es el significado previsto de "objeto compañero"? ¿Por qué se llama "compañero"?

    Primero, Kotlin no usa el concepto Java de staticmiembros porque Kotlin tiene su propio concepto de objects para describir propiedades y funciones relacionadas con el estado singleton, y staticparte de Java de una clase puede expresarse elegantemente en términos de singleton: es un objeto singleton que se puede llamar por el nombre de la clase. De ahí el nombre: es un objeto que viene con una clase.

    Su nombre solía ser class objectydefault object , pero luego cambió su nombre por elcompanion object que es más claro y también es coherente con los objetos complementarios de Scala .

    Además de nombrar, es más poderoso que los staticmiembros de Java : puede extender clases e interfaces, y puede hacer referencia y pasarlo como cualquier otro objeto.

  • ¿Significa que para crear múltiples propiedades estáticas, tengo que agruparlo dentro del companion objectbloque?

    Sí, esa es la forma idiomática. O incluso puede agruparlos en objetos no complementarios por su significado:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • Para crear instantáneamente una instancia singleton que tenga un alcance para una clase, a menudo escribo lo /*...*/que parece una forma unidiomática de hacerlo. ¿Cuál es la mejor manera?

    Depende de lo que necesite en cada caso particular. Su código se adapta bien para almacenar el estado vinculado a una clase que se inicializa en la primera llamada.

    Si no necesita que esté conectado con una clase, solo use la declaración de objeto:

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

    También puede eliminar la lazy { ... }delegación para hacer que la propiedad se inicialice con el uso de primera clase, al igual que los inicializadores estáticos de Java

    También puede encontrar formas útiles de inicializar el estado singleton .

tecla de acceso directo
fuente
Simpáticos e idiomáticos ejemplos.
Trein
19

¿Por qué se llama "compañero"?

Este objeto es un compañero de las instancias. IIRC hubo una larga discusión aquí: próximo-cambio-clase-objetos-repensado

¿Significa que para crear múltiples propiedades estáticas, tengo que agruparlas dentro del bloque de objetos complementarios?

Si. Cada propiedad / método "estático" debe colocarse dentro de este compañero.

Para crear instantáneamente una instancia de singleton que tenga el alcance de una clase, a menudo escribo

No crea la instancia singleton al instante. Se crea al acceder singletonpor primera vez.

lo que parece una forma unidiomática de hacerlo. ¿Cuál es la mejor manera?

Más bien vaya con object Singleton { }para definir una clase singleton. Consulte: Declaraciones de objetos No es necesario que cree una instancia Singleton, simplemente úsela asíSingleton.doWork()

Solo tenga en cuenta que Kotlin ofrece otras cosas para organizar su código. Ahora hay alternativas a las funciones estáticas simples, por ejemplo, podría utilizar las funciones de nivel superior.

D3xter
fuente
7

¿Por qué se llama "compañero"?

Una declaración de objeto dentro de una clase se puede marcar con la palabra clave complementaria:

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

Se puede llamar a los miembros del objeto complementario simplemente usando el nombre de la clase como calificador:

val instance = MyClass.create()

Si solo usa 'objeto' sin 'compañero', debe hacer lo siguiente:

val instance = MyClass.Factory.create()

Según tengo entendido, 'compañero' significa que este objeto es compañero de la clase externa.

Lyn
fuente
"objeto" sin "compañero" se llama así (MyClass (). create ()). Como un singleton, pero para acceder al objeto singleton primero tiene que inicializar la clase "externa".
LiTTle
0

Podemos decir que el compañero es el mismo que el "Bloque estático" como Java, pero en el caso de Kotlin no hay un concepto de Bloque estático, entonces el compañero entra en el marco.

Cómo definir un bloque complementario:

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

Método de llamada del bloque complementario, directo con nombre de clase

Example.Companion.display
Ankur Yadav
fuente