Dlaczego używamy „obiektu towarzyszącego” jako swego rodzaju zamiennika dla statycznych pól Javy w Kotlinie?

145

Jakie jest zamierzone znaczenie „obiektu towarzyszącego”? Do tej pory używałem go tylko do zastępowania Javy, statickiedy jej potrzebuję.

Mylę się z:

  • Dlaczego nazywa się to „towarzyszem”?
  • Czy to oznacza, że ​​aby utworzyć wiele właściwości statycznych , muszę je zgrupować w companion objectbloku?
  • Często piszę, aby natychmiast utworzyć pojedynczą instancję, która jest ograniczona do klasy

:

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

co wydaje się być jednostkowym sposobem na zrobienie tego. Jaki jest lepszy sposób?

Randy Sugianto „Yuku”
źródło

Odpowiedzi:

108
  • Jakie jest zamierzone znaczenie „obiektu towarzyszącego”? Dlaczego nazywa się to „towarzyszem”?

    Po pierwsze, Kotlin nie używa koncepcji elementów staticczłonkowskich w języku Java, ponieważ Kotlin ma własną koncepcję objects do opisywania właściwości i funkcji związanych ze stanem singletonowym, a staticczęść klasy w języku Java może być elegancko wyrażona w kategoriach singletona: jest to obiekt singletonowy, który można nazwać nazwą klasy. Stąd nazewnictwo: to obiekt, który pochodzi z klasą.

    Jego nazwa była class objectidefault object , ale potem została zmieniona na,companion object która jest bardziej przejrzysta i jest również spójna z obiektami towarzyszącymi Scala .

    Oprócz nazewnictwa ma większe możliwości niż staticelementy składowe Java : może rozszerzać klasy i interfejsy, a także odwoływać się do niego i przekazywać go tak, jak inne obiekty.

  • Czy to oznacza, że ​​aby utworzyć wiele właściwości statycznych, muszę je zgrupować w companion objectbloku?

    Tak, to idiomatyczny sposób. Lub możesz nawet pogrupować je w obiekty niebędące towarzyszami według ich znaczenia:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • Aby natychmiast utworzyć pojedynczą instancję, która jest ograniczona do klasy, często piszę, /*...*/co wydaje się być jednostajnym sposobem zrobienia tego. Jaki jest lepszy sposób?

    To zależy od tego, czego potrzebujesz w każdym konkretnym przypadku. Twój kod dobrze nadaje się do przechowywania stanu związanego z klasą, która jest inicjowana przy pierwszym wywołaniu jej.

    Jeśli nie potrzebujesz, aby był połączony z klasą, po prostu użyj deklaracji obiektu:

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

    Możesz również usunąć lazy { ... }delegowanie, aby właściwość była inicjowana przy użyciu pierwszej klasy, podobnie jak inicjatory statyczne Java

    Możesz również znaleźć przydatne sposoby inicjowania stanu singleton .

Klawisz skrótu
źródło
Ładne i idiomatyczne przykłady.
Trein
19

Dlaczego nazywa się to „towarzyszem”?

Ten obiekt jest towarzyszem instancji. IIRC toczyła się tu długa dyskusja: przemyślenie nadchodzącej zmiany klasy obiektów

Czy to oznacza, że ​​aby utworzyć wiele właściwości statycznych, muszę je zgrupować w bloku obiektu towarzyszącego?

Tak. Każda „statyczna” właściwość / metoda musi zostać umieszczona wewnątrz tego elementu towarzyszącego.

Często piszę, aby natychmiast utworzyć pojedynczą instancję, która jest ograniczona do klasy

Nie tworzysz instancji singleton od razu. Jest tworzony podczas singletonpierwszego dostępu .

co wydaje się być jednostkowym sposobem na zrobienie tego. Jaki jest lepszy sposób?

Raczej idź object Singleton { }do zdefiniowania klasy singleton. Zobacz: Deklaracje obiektów Nie musisz tworzyć instancji Singleton, po prostu używaj jej w ten sposóbSingleton.doWork()

Pamiętaj tylko, że Kotlin oferuje inne rzeczy do uporządkowania kodu. Istnieją teraz alternatywy dla prostych funkcji statycznych, np. Zamiast tego można użyć funkcji najwyższego poziomu.

D3xter
źródło
7

Dlaczego nazywa się to „towarzyszem”?

Deklarację obiektu wewnątrz klasy można oznaczyć słowem kluczowym companion:

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

Elementy członkowskie obiektu towarzyszącego można wywołać, używając po prostu nazwy klasy jako kwalifikatora:

val instance = MyClass.create()

Jeśli używasz tylko „obiektu” bez „towarzysza”, musisz zrobić to w następujący sposób:

val instance = MyClass.Factory.create()

W moim rozumieniu „towarzysz” oznacza, że ​​ten obiekt jest towarzyszem klasy zewnętrznej.

Lyn
źródło
„Obiekt” bez „towarzysza” jest nazywany w ten sposób (MyClass (). create ()). Podobnie jak w przypadku singletona, ale aby uzyskać dostęp do obiektu singleton, musisz najpierw zainicjować klasę „zewnętrzną”.
LiTTle
0

Można powiedzieć, że towarzysz jest taki sam jak „Blok statyczny”, jak Java, ale w przypadku Kotlina nie ma koncepcji bloku statycznego, w ramce pojawia się towarzysz.

Jak zdefiniować blok towarzyszący:

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

Metoda wywoływania bloku towarzyszącego, bezpośrednio z nazwą klasy

Example.Companion.display
Ankur Yadav
źródło