Чому ми використовуємо “супровідний об’єкт” як своєрідну заміну статичних полів Java в Котліні?


145

Яке значення має на увазі «супутник об’єкта»? Поки я використовую його просто для заміни Java, staticколи мені це потрібно.

Мене плутають:

  • Чому його називають «супутником»?
  • Чи означає це, що для створення декількох статичних властивостей я повинен згрупувати їх разом у companion objectблоці?
  • Щоб миттєво створити однотонний екземпляр, який охоплюється класом, я часто пишу

:

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

що здається однозначним способом зробити це. Який кращий спосіб?

Відповіді:


108
  • Яке значення має на увазі «супутник об’єкта»? Чому його називають «супутником»?

    По-перше, Котлін не використовує поняття Java staticчленів, тому що у Котліна є своя концепція objects для опису властивостей і функцій, пов'язаних з однотонним станом, і staticчастина Java класу може бути вишукано виражена через синглтон: це однотонний об'єкт, який можна назвати ім'ям класу. Звідси іменування: це об'єкт, який поставляється з класом.

    Його ім'я раніше class objectіdefault object , але тоді він був перейменований вcompanion object який є більш ясним , а також в відповідності з об'єктами Scala компаньйонів .

    Крім імен, він є більш потужним, ніж staticчлени Java : він може розширювати класи та інтерфейси, а ви можете посилатись та передавати їх навколо, як і інші об'єкти.

  • Чи означає це, що для створення декількох статичних властивостей я повинен згрупувати їх разом у companion objectблоці?

    Так, це ідіоматичний шлях. Або ви навіть можете згрупувати їх у супутні об’єкти за їх значенням:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • Щоб миттєво створити однотонний екземпляр, який охоплюється класом, я часто пишу, /*...*/що здається однозначним способом зробити це. Який кращий спосіб?

    Це залежить від того, що вам потрібно в кожному конкретному випадку. Ваш код добре підходить для зберігання стану, прив'язаного до класу, який ініціалізується при першому виклику до нього.

    Якщо вам не потрібно, щоб він був з'єднаний з класом, просто використовуйте оголошення об’єкта:

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

    Ви також можете видалити lazy { ... }делегування, щоб зробити властивість ініціалізувати під час використання першого класу, як і статичні ініціалізатори Java

    Можливо, ви також знайдете корисні способи ініціалізації одиночного стану .


Приємні та ідіоматичні приклади.
Потяг

19

Чому його називають «супутником»?

Цей об’єкт є супутником екземплярів. У IIRC тут тривали дискусії: майбутні-зміни-клас-об’єкти-переосмислені

Чи означає це, що для створення декількох статичних властивостей я мушу групувати їх разом у супутнім об’єктному блоці?

Так. Кожне "статичне" властивість / метод потрібно розмістити всередині цього супутника.

Щоб миттєво створити однотонний екземпляр, який охоплюється класом, я часто пишу

Ви не створюєте одиничний екземпляр моментально. Він створюється при singletonпершому зверненні .

що здається однозначним способом зробити це. Який кращий спосіб?

Швидше переходьте object Singleton { }до визначення однокласного класу. Див.: Декларації об’єктів Не потрібно створювати екземпляр Singleton, просто використовуйте його такSingleton.doWork()

Тільки майте на увазі, що Котлін пропонує інші речі для організації вашого коду. Зараз існують альтернативи простим статичним функціям, наприклад, ви можете використовувати замість них функції верхнього рівня.


7

Чому його називають «супутником»?

Декларація об'єкта всередині класу може бути позначена ключовим словом-супутником:

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

Члени об'єкта-супутника можна викликати, використовуючи просто ім'я класу як класифікатор:

val instance = MyClass.create()

Якщо ви використовуєте лише "об'єкт" без "супутника", ви повинні зробити так:

val instance = MyClass.Factory.create()

На моє розуміння, «компаньйон» означає, що цей об’єкт є компаньйоном з класом «outter».


"об'єкт" без "супутника" називається так (MyClass (). create ()). Як і синглтон, але для доступу до одиночного об'єкта потрібно спочатку ініціалізувати "зовнішній" клас.
LiTTle

0

Можна сказати, що супутник такий же, як "Статичний блок", як Java, але у випадку Котліна немає концепції статичного блоку, ніж супутник потрапляє в кадр.

Як визначити блок-супровід:

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

Метод виклику супутнього блоку, прямий з назвою класу

Example.Companion.display
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.