companion object — Kotlin dilinin mexanizmi, sinfin statik üzvlərini elan etmək üçün Java-dakı static açar sözünü əvəz edir. Kotlin-də daxili static yoxdur — bunun əvəzinə sinif daxilində companion modifikatoru ilə object elanı istifadə olunur. JetBrains, 2025-ə görə, companion object sinif adı vasitəsilə metod və xassələri çağırmağa imkan verir ki, bu da onları Java ekosistemindəki statik üzvlərin tam analoqu edir.
Əsas məqamlar
companion object — Kotlin dilində object declaration-ın xüsusi növüdür və companion açar sözü ilə işarələnir. O, sinfə aid olan üzvləri, yəni Java terminologiyasında statik üzvləri elan etməyə imkan verir. Java-da static ayrı-ayrı sahə və metodlar üçün modifikator olduğu halda, Kotlin-də statik üzvlər bir obyekt-yoldaş daxilində qruplaşdırılır.
Kotlin-də istənilən sinif dəqiq bir companion object sahibi ola bilər. Bu obyektin üzvlərinə sinif adı vasitəsilə nümunə yaratmadan giriş mümkündür: MyClass.method(). Eyni zamanda bayt-kod baxımından companion object ayrıca daxili sinfə kompilyasiya olunur və onun metodları @JvmStatic annotasiyası ilə xarici sinfin statik metodlarına çevrilir.
Google I/O 2024-ə görə, companion object müasir Kotlin Android tətbiqlərində fabrik metodları, sabitlər və köməkçi funksiyalar üçün əsas nümunəyə çevrilmişdir. Tərtibatçılar paket funksiyaları olan köməkçi siniflər əvəzinə onu seçirlər, çünki companion object sahib siniflə məntiqi əlaqəni qoruyur.
Statik konteksti qruplaşdırmaq üçün companion object-dən istifadə edin — sinfə məntiqi aid olan, lakin nümunə tələb etməyən sabitlər, fabriklər, köməkçi metodlar.
Companion object-in əsas sintaksisi sadədir: companion açar sözü sinif daxilində object elanından əvvəl yerləşdirilir. Ad göstərilməzsə, obyekt Companion adını alır və ona açıq və ya gizli şəkildə müraciət etmək olar.
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 }
}
// Sinif adı ilə giriş
val table = User.TABLE_NAME
val user = User.create("Alice")
Yuxarıdakı nümunədə TABLE_NAME və create() User.TABLE_NAME və User.create() vasitəsilə əlçatandır. Primitiv sabitlər üçün const modifikatoruna diqqət yetirin — o, dəyərin kompilyasiya mərhələsində yerləşdirilməsini təmin edir, Java-dakı static final ilə eyni şəkildə.
Companion object-in adı yoxdursa, ona avtomatik Companion adı ilə müraciət etmək olar: User.Companion.TABLE_NAME. Praktikada bu nadir hallarda tələb olunur, lakin Java kodundan çağırış zamanı və ya reflektivadan istifadə edərkən faydalıdır.
// Hər iki çağırış ekvivalentdir
User.create("Bob")
User.Companion.create("Bob")
// Companion object-ə istinad əldə etmək
val companion: User.Companion = User
companion object bir ada sahib ola bilər ki, bu da kodun oxunaqlılığını artırır və ona başa düşülən adla müraciət etməyə imkan verir. Factory — fabrik kimi istifadə olunan companion object üçün ən geniş yayılmış addır.
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 adı ilə giriş
val response = HttpResponse.Factory.ok("data")
Adlı companion object statik üzvlərin məqsədini sənədləşdirməyə kömək edir. Refaktoring zamanı ad kodu özünü-sənədləşdirən edir — tərtibatçı dərhal görür ki, Factory HttpResponse nümunələri yaradır.
Sinif yalnız bir companion object sahibi ola bilər. Bu, Java-dan əsas fərqdir — Java-da qruplaşdırmadan istənilən sayda statik sahə və metod elan etmək olar. Bir neçə məntiqi statik üzv qrupu lazımdırsa, companion olmadan iç-içə object declarations istifadə edin.
Rəsmi Kotlin sənədlərinə görə (Kotlin Docs, 2025), bir companion object məhdudiyyəti dilin dizaynı ilə motivasiya olunub: statik üzvlər siniflə sıx bağlı olmalıdır və bir obyekt-yoldaş bu əlaqənin aydın sərhədini təmin edir. Statik üzvlər çoxdursa — bu sinfin refaktoringi üçün siqnaldır.
Kotlin-də interfeyslər də companion object sahibi ola bilər. Bu, Java-da mümkün olmayan şəkildə, birbaşa interfeys daxilində statik metodlar və sabitlər təyin etməyə imkan verir. Bu yanaşma tez-tez interfeyslə əlaqəli sabitlərin və ya fabrik metodlarının elanı üçün istifadə olunur.
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)
}
}
Bu nümunədə BASE_URL, TIMEOUT_MS və create() ApiService interfeysinə aiddir, onun reallaşdırmalarına deyil. Bu rahatdır: API xidmətinin nümunəsini yaratmaq üçün bütün sabitlər və fabrik məntiqi bir yerdə — interfeysin özü daxilində yerləşir.
İnterfeysin reallaşdırmaları companion object üzvlərini miras almır — onlar yalnız interfeysin adı vasitəsilə çağırılır: ApiService.BASE_URL.
Java kodundan companion object metodlarını çağırarkən onlar defolt olaraq Companion daxili sinfinin metodları kimi əlçatandır, xarici sinfin statik metodları kimi deyil. Onları Java üçün həqiqi static metod və sahə kimi ixrac etmək üçün metodlar üçün @JvmStatic, sahələr üçün @JvmField annotasiyasından istifadə edin.
| Annotasiya | Tətbiq | Java-da nəticə |
|---|---|---|
| @JvmStatic | Companion object metodları | Statik metod: ClassName.method() |
| @JvmField | Companion object sahələri | Statik sahə: ClassName.field |
| const | Primitivlər və String | Inline-sabit: kompilyator dəyəri yerləşdirir |
| annotasiyasız | Defolt metodlar/sahələr | 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-da MathUtils.square(5), MathUtils.TAG kimi çağırılır
@JvmStatic istifadəsi Java kodundan əlçatan olmalı olan bütün ictimai companion object metodları üçün tövsiyə olunur. const yalnız primitiv tiplərə və String-ə tətbiq olunur — qalan tiplər üçün @JvmField istifadə edin.
Real layihələrdə companion object bir neçə standart ssenari üçün tətbiq olunur. Fabrik metodları — ən geniş yayılmış nümunədir: müxtəlif imzalı çoxsaylı konstruktorlar əvəzinə companion object-də adlı fabrik metodları istifadə olunur.
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>()
NetworkResult-də companion object düzgün generic tipi ilə Loading nümunəsi yaradan loading() fabrik metodunu təqdim edir. Bu metod olmadan birbaşa Loading() vasitəsilə nümunə yaratmaq lazım gələrdi ki, bu da daxili reallaşdırmanı açıqlayır.
Tez-tez companion object sinfə spesifik sabitləri saxlamaq üçün istifadə olunur. const val ilə elan edilmiş sabitlər kompilyasiya mərhələsində yerləşdirilir ki, bu da icra vaxtında sıfır yük verir.
class UserRepository {
companion object {
private const val TAG = "UserRepository"
private const val CACHE_SIZE = 100
private const val DEFAULT_PAGE_SIZE = 20
}
}
Tez-tez verilən suallar
ordinary object — sinifdən asılı olmayaraq mövcud olan tamhüquqlu sinqlton-dur. companion object — sinif daxilində object-dir, onun üzvləri xarici sinfin adı vasitəsilə çağırılır. Bayt-kodda companion object statik iç-içə sinfə çevrilir, adi object isə avtonom sinqlton-sinfə çevrilir.
Xeyr, companion object alt siniflər tərəfindən miras alınmır. Əgər B sinfi A sinfindən miras alırsa, B.method() A sinfinin companion object-dən metodu çağırmayacaq — A.method() vasitəsilə müraciət etmək lazımdır. Bu, Java-da statik metodların davranışına uyğundur.
Defolt olaraq — ClassName.Companion.method() vasitəsilə. Statik metod kimi çağırmaq üçün companion object metoduna @JvmStatic əlavə edin. Sahələr üçün @JvmField istifadə edin və ya primitivlər üçün onları const val ilə elan edin.
Kotlin tərtibatçıları obyektlərlə vahid iş üçün static-dən imtina edərək companion object-i seçmişlər. Java-da static OOP prinsiplərini pozur, çünki statik metodlar nümunə ilə əlaqəli deyil. companion object — birinci dərəcəli obyektdir, onu ötürmək, genişləndirmə funksiyaları ilə genişləndirmək və interfeysləri reallaşdırmaq mümkündür.
const val istifadə edərkən primitivlər və String üçün — sıfır yük, dəyər bayt-koda yerləşdirilir. Metodlar üçün yük yoxdur, əgər metod inline deyilsə. Əksər hallarda companion object performansa ölçülə bilən təsir göstərmir. @JvmStatic-dən yalnız Java-dan çağırılan ictimai API üçün istifadə edin.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun