Perché utilizziamo "oggetto compagno" come una sorta di sostituzione per i campi statici Java in Kotlin?


145

Qual è il significato previsto di "oggetto associato"? Finora l'ho usato solo per sostituire Java staticquando ne ho bisogno.

Sono confuso con:

  • Perché si chiama "compagno"?
  • Significa che per creare più proprietà statiche , devo raggrupparle all'interno del companion objectblocco?
  • Per creare istantaneamente un'istanza singleton che ha come scopo una classe, scrivo spesso

:

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

che sembra un modo unidiomatico di farlo. Qual è il modo migliore?

Risposte:


108
  • Qual è il significato previsto di "oggetto associato"? Perché si chiama "compagno"?

    Innanzitutto, Kotlin non usa il concetto Java dei staticmembri perché Kotlin ha il suo concetto di objects per descrivere proprietà e funzioni connesse allo stato singleton, e staticparte Java di una classe può essere elegantemente espressa in termini di singleton: è un oggetto singleton che può essere chiamato dal nome della classe. Da qui la denominazione: è un oggetto che viene fornito con una classe.

    Il suo nome era class objectedefault object , ma poi è stato rinominato in modocompanion object che sia più chiaro ed è anche coerente con gli oggetti companion Scala .

    Oltre alla denominazione, è più potente dei staticmembri Java : può estendere classi e interfacce e puoi fare riferimento e passarlo come altri oggetti.

  • Vuol dire che per creare più proprietà statiche, devo raggrupparlo all'interno del companion objectblocco?

    Sì, questo è il modo idiomatico. Oppure puoi anche raggrupparli in oggetti non associati in base al loro significato:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • Per creare istantaneamente un'istanza singleton che ha come scopo una classe, scrivo spesso /*...*/che sembra un modo unidiomatico di farlo. Qual è il modo migliore?

    Dipende da cosa ti serve in ogni caso particolare. Il codice si adatta bene per la memorizzazione dello stato associato a una classe inizializzata alla prima chiamata.

    Se non è necessario che sia connesso a una classe, utilizzare semplicemente la dichiarazione dell'oggetto:

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

    È inoltre possibile rimuovere la lazy { ... }delega per inizializzare la proprietà all'utilizzo della prima classe, proprio come gli inizializzatori statici Java

    Potresti anche trovare modi utili per inizializzare lo stato singleton .


Esempi carini e idiomatici.
Trein,

19

Perché si chiama "compagno"?

Questo oggetto è un compagno delle istanze. IICR qui si è discusso a lungo: il cambio di classe in arrivo ha ripensato

Vuol dire che per creare più proprietà statiche, devo raggrupparle all'interno del blocco oggetto compagno?

Sì. Ogni proprietà / metodo "statico" deve essere inserito in questo compagno.

Per creare istantaneamente un'istanza singleton che ha come scopo una classe, scrivo spesso

Non si crea immediatamente l'istanza singleton. Viene creato quando si accede singletonper la prima volta.

che sembra un modo unidiomatico di farlo. Qual è il modo migliore?

Piuttosto vai con object Singleton { }per definire una classe singleton. Vedi: Dichiarazioni di oggetti Non è necessario creare un'istanza di Singleton, basta usarla cosìSingleton.doWork()

Tieni presente che Kotlin offre altre cose per organizzare il tuo codice. Esistono ora alternative alle semplici funzioni statiche, ad esempio è possibile utilizzare le funzioni di livello superiore.


7

Perché si chiama "compagno"?

Una dichiarazione di oggetto all'interno di una classe può essere contrassegnata con la parola chiave companion:

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

I membri dell'oggetto associato possono essere chiamati semplicemente usando il nome della classe come qualificatore:

val instance = MyClass.create()

Se usi solo 'oggetto' senza 'compagno', devi fare così:

val instance = MyClass.Factory.create()

A mio avviso, "compagno" significa che questo oggetto è compagno della classe esterna.


"object" senza "companion" si chiama così (MyClass (). create ()). Come un singleton, ma per accedere all'oggetto singleton devi prima inizializzare la classe "esterna".
LuTTle

0

Possiamo dire che il compagno è lo stesso di "Blocco statico" come Java, ma nel caso di Kotlin non esiste un concetto di blocco statico, quindi il compagno entra nel frame.

Come definire un blocco companion:

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

Metodo di chiamata del blocco companion, diretto con il nome della classe

Example.Companion.display
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.