Котлинский объект против объекта-компаньона

Недавно я столкнулся с вопросом во время проверки кода. Это было в контексте PR, где использовались kotlin class и куча функций внутри companion object {}, помеченных как @JvmStatic для взаимодействия с Java. Ответ был таким: «Почему мы не можем преобразовать class в object и избавиться от _6 _?» Это вызвало вопрос "what is the benefit with that?". Было дано какое-то объяснение, но я не был полностью удовлетворен данным объяснением (мной :)). Итак, я решил немного почитать и задокументировать различия и варианты использования для моей будущей справки и для тех, кто наткнется на аналогичный вопрос.

Объект

Object в котлине - это способ реализации Singletons. Все мы сталкивались с необходимостью Singleton шаблона в нашей карьере для различных сценариев использования. Что ж, в котлине это сделано очень просто.
например

Эта реализация также называется object declaration. Объявления объектов являются потокобезопасными и lazy initialized, т.е. объекты инициализируются при первом доступе к ним.

Сопутствующий объект

Если мы хотим, чтобы какая-то реализация была class, но все же хотим показать какое-то поведение как static поведение, companion object вступаем в игру. Это object declarations внутри класса. Эти сопутствующие объекты инициализируются при разрешении содержащего класса, аналогично static методам и переменным в мире Java.
например.

Резюме

Учитывая приведенное выше объяснение, вариант использования полностью зависит от проблемы, которую мы пытаемся решить. Если нам нужно обеспечить поведение Singleton, тогда нам будет лучше с Objects, иначе, если мы просто хотим добавить немного static essence в наши классы, мы можем использовать Companion objects.

Бонус - доступ к объектам и компаньонам из Java

@JvmField, lateinit, const, @JvmStatic удобны, когда дело доходит до доступа к свойствам поля или функциям, определенным в objects или companion objects.
например наш object может быть примерно таким, как показано ниже

Из Java мира мы можем получить доступ к этим функциям как:

MyObject.printStaticHello() OR MyObject.INSTANCE.printNonStaticHello() - this uses the singleton instance

Доступ к companion object

Из Java мира мы можем получить к ним доступ как:

MyClass.printStaticHello() 
MyClass.Companion.printStaticHello() MyClass.Companion.printNonStaticHello()

Спасибо за чтение.
Примечание. Дополнительная литература и ссылки, здесь и здесь

Первоначально опубликовано на https://dev.to 9 марта 2020 г.