Mengapa kita menggunakan "objek pengiring" sebagai pengganti bidang statis Java di Kotlin?

145

Apa arti dari "objek pengiring"? Sejauh ini saya telah menggunakannya hanya untuk mengganti Java staticketika saya membutuhkannya.

Saya bingung dengan:

  • Mengapa disebut "teman"?
  • Apakah ini berarti bahwa untuk membuat beberapa properti statis , saya harus mengelompokkannya di dalam companion objectblok?
  • Untuk secara instan membuat instance singleton yang dicakup dalam suatu kelas, saya sering menulis

:

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

yang sepertinya merupakan cara tidak langsung untuk melakukannya. Apa cara yang lebih baik?

Randy Sugianto 'Yuku'
sumber

Jawaban:

108
  • Apa arti dari "objek pengiring"? Mengapa disebut "teman"?

    Pertama, Kotlin tidak menggunakan konsep Java dari staticanggota karena Kotlin memiliki sendiri konsep objects untuk menggambarkan sifat dan fungsi terhubung dengan negara tunggal, dan Jawa staticbagian dari sebuah kelas dapat elegan dinyatakan dalam hal tunggal: itu adalah objek tunggal yang dapat dipanggil dengan nama kelas '. Oleh karena itu penamaan: itu adalah objek yang dilengkapi dengan kelas.

    Namanya dulu class objectdandefault object , tapi kemudian diganti namanya menjadicompanion object yang lebih jelas dan juga konsisten dengan objek pendamping Scala .

    Selain dari penamaan, ini lebih kuat daripada staticanggota Java : ia dapat memperluas kelas dan antarmuka, dan Anda dapat referensi dan menyebarkannya seperti objek lainnya.

  • Apakah ini berarti bahwa untuk membuat beberapa properti statis, saya harus mengelompokkannya di dalam companion objectblok?

    Ya, itulah cara idiomatisnya. Atau Anda bahkan dapat mengelompokkannya dalam objek non-pengiring dengan artinya:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • Untuk secara instan membuat instance tunggal yang dicakup ke dalam kelas, saya sering menulis /*...*/yang sepertinya merupakan cara yang tidak otomatis untuk melakukannya. Apa cara yang lebih baik?

    Itu tergantung pada apa yang Anda butuhkan dalam setiap kasus tertentu. Kode Anda cocok untuk menyimpan status terikat ke kelas yang diinisialisasi pada panggilan pertama ke sana.

    Jika Anda tidak perlu terhubung dengan kelas, cukup gunakan deklarasi objek:

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

    Anda juga dapat menghapus lazy { ... }delegasi untuk membuat properti diinisialisasi pada penggunaan kelas satu, seperti halnya initializers statis Java

    Anda mungkin juga menemukan cara yang berguna untuk menginisialisasi keadaan tunggal .

hotkey
sumber
Contoh yang bagus dan idiomatis.
Trein
19

Mengapa disebut "teman"?

Objek ini adalah pendamping dari instance. IIRC ada diskusi panjang di sini: mendatang-ubah-kelas-objek-dipikirkan kembali

Apakah itu berarti bahwa untuk membuat beberapa properti statis, saya harus mengelompokkannya di dalam blok objek pengiring?

Iya. Setiap properti / metode "statis" harus ditempatkan di dalam pendamping ini.

Untuk secara instan membuat instance singleton yang dicakup dalam suatu kelas, saya sering menulis

Anda tidak membuat instance singleton secara instan. Itu dibuat saat mengakses singletonuntuk pertama kalinya.

yang sepertinya merupakan cara tidak langsung untuk melakukannya. Apa cara yang lebih baik?

Lebih baik pergi dengan object Singleton { }mendefinisikan kelas tunggal. Lihat: Deklarasi Objek Anda tidak perlu membuat instance Singleton, cukup gunakan seperti ituSingleton.doWork()

Perlu diingat bahwa Kotlin menawarkan hal-hal lain untuk mengatur kode Anda. Sekarang ada alternatif untuk fungsi statis sederhana misalnya Anda bisa menggunakan Fungsi Tingkat Top.

D3xter
sumber
7

Mengapa disebut "teman"?

Deklarasi objek di dalam kelas dapat ditandai dengan kata kunci pengiring:

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

Anggota objek pendamping dapat dipanggil dengan hanya menggunakan nama kelas sebagai kualifikasi:

val instance = MyClass.create()

Jika Anda hanya menggunakan 'objek' tanpa 'teman', Anda harus melakukan ini:

val instance = MyClass.Factory.create()

Dalam pemahaman saya, 'pendamping' berarti objek ini adalah pendamping dengan kelas outter.

Lyn
sumber
"objek" tanpa "pendamping" disebut seperti ini (MyClass (). create ()). Seperti seorang singleton, tetapi untuk mengakses objek singleton Anda harus menginisialisasi kelas "luar" terlebih dahulu.
LiTTle
0

Kita dapat mengatakan bahwa teman sama dengan "Blok Statis" seperti Jawa, tetapi dalam kasus Kotlin tidak ada konsep Blok Statis, daripada teman masuk ke bingkai.

Cara mendefinisikan blok pengiring:

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

Metode panggilan blok pendamping, langsung dengan nama kelas

Example.Companion.display
Ankur Yadav
sumber