← Назад к вопросам

Что такое companion object?

1.0 Junior🔥 71 комментариев
#Другое

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое companion object в Kotlin?

Companion object (спутниковый объект) — это специальный объект, объявляемый внутри класса, который существует в единственном экземпляре и связан с классом, а не с его конкретными экземплярами. По сути, это объект-одиночка (singleton), вложенный в класс, но доступный через имя класса напрямую.

Ключевые характеристики и назначение

  1. Аналог статических членов в Java В Kotlin нет ключевого слова static. Companion object служит заменой статических методов и полей, но с более богатыми возможностями. Он позволяет группировать функции и свойства, логически связанные с классом, но не требующие экземпляра.

  2. Доступ через имя класса Члены companion object доступны без создания экземпляра класса, что удобно для утилитных функций, фабричных методов или констант.

class MyClass {
    companion object {
        const val TAG = "MyClass"
        fun create(): MyClass = MyClass()
    }
}

// Использование
val tag = MyClass.TAG
val instance = MyClass.create()
  1. Реализация интерфейсов В отличие от статических методов Java, companion object может реализовывать интерфейсы, что открывает возможности для полиморфизма.
interface Factory<T> {
    fun create(): T
}

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

fun makeInstance(factory: Factory<MyClass>) = factory.create()
val obj = makeInstance(MyClass) // Передаем companion object как реализацию Factory
  1. Расширения (extensions) Для companion object можно объявлять функции-расширения, что полезно для организации кода.
class MyClass {
    companion object
}

fun MyClass.Companion.specialFunction() = println("Companion extension")

// Вызов
MyClass.specialFunction()

Отличия от обычного object

  • Обычный object внутри класса создаёт отдельный singleton для каждого экземпляра класса (если он не вложен в другой object).
  • Companion object всегда один на класс и связан с классом, а не с экземплярами.
class Outer {
    companion object {
        // Один на класс Outer
    }
    
    object InnerObject {
        // Отдельный singleton, но тоже один (доступ через Outer.InnerObject)
    }
}

Практические примеры использования

Фабричные методы и альтернативные конструкторы:

class User private constructor(val name: String) {
    companion object {
        fun createByName(name: String): User {
            return User(name.validate())
        }
        
        fun createByEmail(email: String): User {
            return User(email.extractUsername())
        }
    }
    
    private fun String.validate(): String = this.trim()
    private fun String.extractUsername(): String = this.substringBefore("@")
}

Хранение констант и общих данных:

class DatabaseConfig {
    companion object {
        const val DEFAULT_PORT = 5432
        const val TIMEOUT_MS = 5000
        val SUPPORTED_VERSIONS = listOf("1.0", "2.0", "3.0")
    }
}

Ленивая инициализация:

class HeavyResource {
    companion object {
        val resource by lazy {
            // Инициализация выполняется только при первом обращении
            loadHeavyResource()
        }
        
        private fun loadHeavyResource(): Resource { /* ... */ }
    }
}

Важные нюансы

  1. Имя companion object может быть задано явно:
class MyClass {
    companion object Named {
        // Доступ: MyClass.Named.function()
    }
}
  1. Обращение из Java-кода требует использования специального поля Companion:
// Java-код
MyClass.Companion.create();
// Или, если companion object имеет имя:
MyClass.Named.create();
  1. Companion object инициализируется при первом обращении к классу (лениво), а не при загрузке класса JVM, что может быть важно для производительности.

Когда использовать companion object

  • Для фабричных методов вместо множества перегруженных конструкторов
  • Для утилитных функций, связанных с классом
  • Для хранения констант, специфичных для класса
  • Для реализации паттернов типа Factory или Singleton внутри класса
  • Для организации кода, когда нужна группировка статической функциональности

Companion object сочетает преимущества статических членов (производительность, доступ без экземпляра) с возможностями объектов Kotlin (реализация интерфейсов, расширения, полноправный член класса). Это мощный инструмент для создания чистой, модульной архитектуры в Kotlin-приложениях.