Neden “tamamlayıcı nesne” yi Kotlin'deki Java statik alanlarının yerini almak için kullanıyoruz?


145

"Eş nesne" nin amaçlanan anlamı nedir? Şimdiye kadar sadece staticihtiyacım olduğunda Java'nın yerine kullanmak için kullanıyorum .

Kafan karıştı:

  • Neden buna "refakatçi" deniyor?
  • Birden fazla statik özellik oluşturmak için bunu companion objectblok içinde birlikte gruplandırmak zorunda olduğum anlamına mı geliyor ?
  • Bir sınıfa dahil edilen tek bir örneği anında oluşturmak için genellikle

:

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

ki bunu unidiomatik bir yol gibi görüyor. Daha iyi yol nedir?

Yanıtlar:


108
  • "Eş nesne" nin amaçlanan anlamı nedir? Neden buna "refakatçi" deniyor?

    Birincisi, Kotlin Java kavramını kullanmaz staticKotlin kendi sahip olduğu üyelerin kavramını objects tekil devlet ile bağlantılı özellikleri ve işlevleri tanımlamak için, ve Java staticbir sınıfın parçası zarif tekiz cinsinden ifade edilebilir: Bir tekil nesne işte sınıfın adı ile çağrılabilir. Dolayısıyla adlandırma: bir sınıfla gelen bir nesne.

    Adı eskiden vardı class objectvedefault object daha sonra yeniden adlandırıldı,companion object ki bu daha net ve aynı zamanda Scala yardımcı nesnelerle tutarlı .

    Adlandırma dışında, Java staticüyelerinden daha güçlüdür : sınıfları ve arabirimleri genişletebilir ve diğer nesneler gibi ona başvurabilir ve iletebilirsiniz.

  • Birden fazla statik özellik oluşturmak için bunu companion objectblok içinde birlikte gruplandırmak zorunda olduğum anlamına mı geliyor ?

    Evet, bu deyimsel yol. Ya da onları tamamlayıcı olmayan nesnelerde anlamlarına göre gruplandırabilirsiniz:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • Bir sınıfa dahil edilen tek bir örneği anında oluşturmak için, genellikle /*...*/bunu unidiomatik bir yol gibi görünüyor. Daha iyi yol nedir?

    Her özel durumda neye ihtiyacınız olduğuna bağlıdır. Kodunuz, ilk çağrıldığında başlatılan bir sınıfa bağlı durumu depolamak için çok uygundur.

    Bir sınıfa bağlanmasına gerek yoksa, nesne bildirimini kullanın:

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

    Ayrıca , Java statik başlatıcıları gibi, mülkün birinci sınıf kullanımında başlatılmasını sağlamak için lazy { ... }temsilci seçimi kaldırabilirsiniz

    Singleton durumunu başlatmanın yararlı yollarını da bulabilirsiniz .


Güzel ve deyimsel örnekler.
Trein

19

Neden buna "refakatçi" deniyor?

Bu nesne, örneklerin bir arkadaşıdır. IIRC burada uzun bir tartışma yaşadı: yaklaşan-değişim-sınıfı-nesneler-yeniden düşünüldü

Birden fazla statik özellik oluşturmak için, onu tamamlayıcı nesne bloğu içinde birlikte gruplamak zorunda olduğum anlamına mı geliyor?

Evet. Her "statik" özellik / yöntemin bu arkadaşın içine yerleştirilmesi gerekir.

Bir sınıfa dahil edilen tek bir örneği anında oluşturmak için genellikle

Tekil örneği anında oluşturmazsınız. singletonİlk kez erişirken oluşturulur .

ki bunu unidiomatik bir yol gibi görüyor. Daha iyi yol nedir?

Bunun yerine object Singleton { }, bir singleton sınıfı tanımlayın. Bkz: Nesne Bildirimleri Bir örnek oluşturmanız gerekmez Singleton, sadece böyle kullanınSingleton.doWork()

Kotlin'in kodunuzu düzenlemek için başka şeyler sunduğunu unutmayın. Artık basit statik işlevlere alternatifler var, örneğin bunun yerine Üst Düzey İşlevleri kullanabilirsiniz.


7

Neden buna "refakatçi" deniyor?

Sınıf içindeki nesne bildirimi tamamlayıcı anahtar kelimeyle işaretlenebilir:

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

Tamamlayıcı nesnenin üyeleri, niteleyici olarak yalnızca sınıf adı kullanılarak çağrılabilir:

val instance = MyClass.create()

'Eşlik' olmadan 'nesne' kullanıyorsanız, bunu yapmanız gerekir:

val instance = MyClass.Factory.create()

Anladığım kadarıyla, 'arkadaş' bu nesnenin dış sınıfla arkadaş olduğu anlamına gelir.


"companion" olmadan "object" bu şekilde adlandırılır (MyClass (). create ()). Bir singleton gibi, ancak singleton nesnesine erişmek için önce "dış" sınıfı başlatmalısınız.
LiTTle

0

Refakatçinin Java gibi "Statik Blok" ile aynı olduğunu söyleyebiliriz, ancak Kotlin durumunda Statik Blok kavramı yoktur, refakatçi çerçeveye gelir.

Tamamlayıcı blok nasıl tanımlanır:

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

Tamamlayıcı sınıf çağırma yöntemi, doğrudan sınıf adıyla

Example.Companion.display
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.