Компонентные объекты обеспечивают возможность реализации интерфейсов

Почему в объектах компаньона Kotlin / Scala могут быть реализованы некоторые интерфейсы, какие преимущества это может иметь? Когда полезно использовать эту функцию?

    Поскольку companion object s является object s, object s может реализовывать интерфейсы (или расширять классы), и нет веских причин запретить его для companion object s в частности.

    Одно распространенное использование в Scala для фабрик: например, Seq , List , Vector и т. Д. Сопутствующие объекты расширяют TraversableFactory поэтому вы можете писать код, работающий с TraversableFactory и передавать любой из них для построения типа, который вы хотите. Например

     def build[CC[X] <: Traversable[X] with GenericTraversableTemplate[X, CC], A](factory: TraversableFactory[CC])(elems: A*) = factory(elems) // build(List)(1,2,3) == List(1, 2, 3) // build(Set)(1,2,3) == Set(1, 2, 3) 

    Аналогично, все сопутствующие объекты класса класса расширяют типы функций.

    Вы используете одноэлементный объект, если вам нужен только один экземпляр определенного класса в программе.

    Например, Scala's Nil реализует List[Nothing] . Вместо каждого типа списка для реализации конкретного Nil есть только один из них.

    В шаблоне typeclass , где у вас есть только один implicit object для соответствующей реализации.

    Кроме того, если вы создадите public static Something в Java, вы создадите это в сопутствующем объекте.

    Я лично нашел их полезными для реализации плагина sbt, который отображает object Blah extends Renderable в файлы blah.html . Узнайте больше о полезности здесь . Я должен был знать, что он реализует эту черту!

    Вы можете использовать companion object s и наследование для некоторого уровня class-lavel или статического полиморфизма.

    Пример 1: Заводы

    Рассмотрим интерфейс

     interface Factory<T> { fun create(): T } 

    Теперь мы создаем класс, который реализует его сопутствующий объект

     class Foo { companion object: Factory<Foo> { override fun create() = Foo() } } 

    Теперь мы можем создать функцию расширения для всех заводов для создания и, например, регистрации объекта.

     fun <T> Factory<T>.createAndLog(): T { val t = create() println(t) return t } 

    Не используйте его так

     Foo.createAndLog() 

    Пример 2: Запросы

    Рассмотрим интерфейс маркера

     interface Queryable<T> 

    Теперь у нас есть два класса User и Article которые представляют таблицы в базе данных, companion object реализует интерфейс.

     class User(val id: String) { companion object: Queryable<User> {} } class Article(val authorId: String) { companion object: : Queryable<Article> {} } 

    Теперь мы можем определить функцию расширения для создания запроса из класса

     fun <T> Queryable<T>.query() = db.createQuery<T>() 

    которую мы можем назвать

     User.query() //or Article.query() 
    Intereting Posts
    kotlin.jvm.KotlinReflectionNotSupportedError: Реализация отражения Kotlin не найдена во время выполнения. Удостоверьтесь, что у вас есть kotlin-reflect.jar Тип несоответствия: выведенный тип – FragmentActivity? но при обновлении библиотеки поддержки до 27.0.0 Kotlin – getPendingIntent с синтаксисом нескольких флагов Android / Kotlin читает файл с помощью Java.io.File: проблема с дорогой как разбирать котлинский код? Поддержка градиента протокола Buffer для Kotlin Android не работает? Как использовать анонимные классы Kotlin в качестве аргументов для собственных функций JavaScript? Использование kotlin с ContentResolver вызвало исключение IllegalArgumentException есть ли ошибка в выбореKey.attachment () в java nio? Нечетное поведение TestObserver при подписке на тему NoSuchMethodError: java.lang.Long.hashCode Как сравнить два массива в Котлине? Встроенный сеттер или Нет для создания неиспользуемого сеттера в Котлине? Инициализация поля, которое имеет геттер и сеттер? Gson setDateFormat исключает, когда дата равна нулю