companion object — механизам језика Kotlin који замењује кључну реч static из Java-е за декларисање статичких чланова класе. У Kotlin-у не постоји уграђени static — уместо тога користи се декларација object са модификатором companion унутар класе. Према JetBrains, 2025, companion object омогућава позивање метода и својстава путем имена класе, што их чини потпуним аналогом статичких чланова у Java екосистему.
Главно
companion object — специјална врста object declaration у језику Kotlin која се означава кључном речи companion. Омогућава декларисање чланова који припадају класи, а не њеним инстанцама — односно статичких чланова у терминологији Java-е. За разлику од Java-е, где је static модификатор за појединачна поља и методе, у Kotlin-у статички чланови се групишу унутар једног објекта-пратиоца.
Свака класа у Kotlin-у може садржати тачно један companion object. Чланови овог објекта су доступни путем имена класе без креирања инстанце: MyClass.method(). Истовремено, са становишта бајт-кода, companion object се компајлира у засебну унутрашњу класу, а његови методи постају статички методи спољашње класе када се користи анотација @JvmStatic.
Према Google I/O 2024, companion object је постао главни образац за фабричке методе, константе и помоћне функције у савременим Android апликацијама на Kotlin-у. Програмери га бирају уместо помоћних класа са пакетним функцијама, јер companion object задржава логичку везу са класом-власником.
Користите companion object за груписање статичког контекста — константи, фабрика, помоћних метода које се логички односе на класу, али не захтевају инстанцу.
Основна синтакса companion object-а је једноставна: кључна реч companion се поставља испред декларације object унутар класе. Ако име није наведено, објекат добија име Companion, којем се може приступити експлицитно или имплицитно.
class User {
companion object {
const val TABLE_NAME = "users"
fun create(name: String): User {
return User(name)
}
}
val name: String
constructor(name: String) { this.name = name }
}
// Приступ путем имена класе
val table = User.TABLE_NAME
val user = User.create("Alice")
У горњем примеру TABLE_NAME и create() су доступни путем User.TABLE_NAME и User.create(). Обратите пажњу на модификатор const за примитивне константе — он гарантује уграђивање вредности у фази компајлирања, аналогно Java static final за primitive и String.
Ако companion object нема име, може му се приступити путем аутоматског имена Companion: User.Companion.TABLE_NAME. У пракси је то ретко потребно, али је корисно при позивању из Java кода или при коришћењу рефлексије.
// Оба позива су еквивалентна
User.create("Bob")
User.Companion.create("Bob")
// Добијање референце на companion object
val companion: User.Companion = User
companion object може имати име, што побољшава читљивост кода и омогућава позивање по разумљивом имену. Factory — најчешће име за companion object који се користи као фабрика.
class HttpResponse {
companion object Factory {
fun ok(body: String): HttpResponse = HttpResponse(200, body)
fun notFound(): HttpResponse = HttpResponse(404, "Not Found")
fun serverError(): HttpResponse = HttpResponse(500, "Internal Error")
}
}
// Приступ путем имена Factory
val response = HttpResponse.Factory.ok("data")
Именовани companion object помаже у документовању намене статичких чланова. При рефакторисању, име чини код самодокументујућим — програмер одмах види да Factory креира инстанце HttpResponse.
Класа може садржати само један companion object. Ово је суштинска разлика од Java-е, где се може декларисати било који број статичких поља и метода без груписања. Ако је потребно више логичких група статичких чланова, користите угњеждене object declarations без companion.
Према званичној документацији Kotlin-а (Kotlin Docs, 2025), ограничење на један companion object мотивисано је дизајном језика: статички чланови треба да буду уско повезани са класом, а један објекат-пратилац обезбеђује јасну границу те везе. Ако статичких чланова има превише — то је сигнал за рефакторисање класе.
У Kotlin-у и интерфејси могу садржати companion object. Ово омогућава дефинисање статичких метода и константи директно унутар интерфејса, што није могуће у Java-и. Овај приступ се често користи за декларисање константи повезаних са интерфејсом или фабричких метода.
interface ApiService {
companion object {
const val BASE_URL = "https://api.example.com"
const val TIMEOUT_MS = 5000
fun create(client: OkHttpClient): ApiService =
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.build()
.create(ApiService::class.java)
}
}
У овом примеру BASE_URL, TIMEOUT_MS и create() припадају интерфејсу ApiService, а не његовим имплементацијама. Ово је згодно: све константе и фабричка логика за креирање инстанце API сервиса налазе се на једном месту — унутар самог интерфејса.
Имплементације интерфејса не наслеђују чланове companion object-а — они се позивају само путем имена интерфејса: ApiService.BASE_URL.
При позивању метода companion object-а из Java кода, они су подразумевано доступни као методи угњеждене класе Companion, а не као статички методи спољашње класе. Да бисте их извезли као праве static методе и поља за Java-у, користите анотацију @JvmStatic за методе и @JvmField за поља.
| Анотација | Примена | Резултат у Java-и |
|---|---|---|
| @JvmStatic | Методи companion object-а | Статички метод: ClassName.method() |
| @JvmField | Поља companion object-а | Статичко поље: ClassName.field |
| const | Примитиви и String | Inline константа: компајлер уграђује вредност |
| без анотације | Методи/поља подразумевано | Companion.method() / Companion.field |
class MathUtils {
companion object {
const val PI = 3.14159
@JvmStatic
fun square(x: Int): Int = x * x
@JvmField
val TAG: String = "MathUtils"
}
}
// Позвано у Java-и као MathUtils.square(5), MathUtils.TAG
Коришћење @JvmStatic се препоручује за све јавне методе companion object-а које треба да буду доступне из Java кода. const се примењује само на примитивне типове и String — за остале типове користите @JvmField.
У реалним пројектима companion object се користи за неколико стандардних сценарија. Фабрички методи — најчешћи образац: уместо више конструктора са различитим потписима користе се именовани фабрички методи у companion object-у.
sealed class NetworkResult<out T> {
data class Success<out T>(val data: T) : NetworkResult<T>()
data class Error(val message: String) : NetworkResult<Nothing>()
companion object {
fun loading<T>(): NetworkResult<T> =
Loading()
}
}
private class Loading<T> : NetworkResult<T>()
companion object у NetworkResult пружа фабрички метод loading() који креира инстанцу Loading са исправним generic типом. Без овог метода морали бисте креирати инстанцу директно путем Loading(), што открива унутрашњу имплементацију.
Често се companion object користи за чување константи специфичних за класу. Константе декларисане са const val се уграђују у фази компајлирања, што даје нулти overhead у рантајму.
class UserRepository {
companion object {
private const val TAG = "UserRepository"
private const val CACHE_SIZE = 100
private const val DEFAULT_PAGE_SIZE = 20
}
}
Често постављана питања
ordinary object — пуноправни синглтон који постоји независно од класе. companion object — object унутар класе чији се чланови позивају путем имена спољашње класе. У бајт-коду companion object постаје статичка угњеждена класа, а обични object — аутономна синглтон класа.
Не, companion object се не наслеђује подкласама. Ако класа B наслеђује класу A, B.method() неће позвати метод из companion object-а класе A — потребно је приступити путем A.method(). Ово одговара понашању статичких метода у Java-и.
Подразумевано — путем ClassName.Companion.method(). Да бисте позивали као статички метод, додајте @JvmStatic методу companion object-а. За поља користите @JvmField или их декларишите са const val за примитиве.
Програмери Kotlin-а су одлучили да се одрекну static-а у корист companion object-а ради једнообразног рада са објектима. static у Java-и нарушава принципе OOP-а, јер статички методи нису повезани са инстанцом. companion object — објекат прве класе који се може прослеђивати, проширивати функцијама-проширењима и имплементирати интерфејсе.
При коришћењу const val за примитиве и String — нулти overhead, вредност се уграђује у бајт-код. За методе overhead не постоји ако метод није inline. У већини случајева companion object нема мерљив утицај на перформансе. Користите @JvmStatic само за јавни API који се позива из Java-е.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође