companion object, bir sınıfın statik üyelerini bildirmek için Java'nın static anahtar sözcüğünü değiştiren Kotlin dil mekanizmasıdır. Kotlin'de yerleşik static yoktur — bunun yerine, bir sınıf içinde companion değiştiricisiyle object bildirimi kullanılır. JetBrains, 2025'e göre, companion object, sınıf adı aracılığıyla metot ve özelliklerin çağrılmasına izin vererek onları Java ekosistemindeki statik üyelerin tam eşdeğeri yapar.
Önemli Noktalar
companion object, Kotlin'de companion anahtar sözcüğüyle işaretlenmiş özel bir object bildirimi türüdür. Örnekler yerine sınıfa ait olan üyeleri — yani Java terimleriyle statik üyeleri — bildirmeye izin verir. static'in tek tek alanlar ve metotlar için bir değiştirici olduğu Java'nın aksine, Kotlin'de statik üyeler tek bir yoldaş nesne içinde gruplanır.
Kotlin'deki herhangi bir sınıf tam olarak bir companion object içerebilir. Bu nesnenin üyelerine bir örnek oluşturmadan sınıf adı aracılığıyla erişilebilir: MyClass.method(). Bayt kodu açısından, companion object ayrı bir iç sınıf olarak derlenir ve @JvmStatic ek açıklaması kullanıldığında metotları dış sınıfın statik metotları haline gelir.
Google I/O 2024'e göre, companion object, Kotlin'de yazılan modern Android uygulamalarında fabrika metotları, sabitler ve yardımcı işlevler için ana model haline gelmiştir. Geliştiriciler, paket düzeyinde işlevlere sahip yardımcı sınıflar yerine bunu tercih eder çünkü companion object, sahip sınıfla mantıksal bağlantıyı korur.
Statik bağlamı — sabitleri, fabrikaları, mantıksal olarak sınıfa ait olan ancak bir örnek gerektirmeyen yardımcı metotları — gruplamak için companion object kullanın.
companion object'in temel sözdizimi basittir: companion anahtar sözcüğü, sınıf içindeki object bildiriminin önüne yerleştirilir. Bir ad belirtilmezse, nesne Companion adını alır ve açık veya örtük olarak erişilebilir.
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 }
}
// Access via class name
val table = User.TABLE_NAME
val user = User.create("Alice")
Yukarıdaki örnekte, TABLE_NAME ve create()'e User.TABLE_NAME ve User.create() aracılığıyla erişilebilir. İlkel sabitler için const değiştiricisine dikkat edin — derleme zamanında değer eklemesini garanti eder, ilkeller ve String için Java static final'e benzer.
Bir companion object'in adı yoksa, otomatik ad Companion: User.Companion.TABLE_NAME aracılığıyla erişilebilir. Pratikte bu nadiren gereklidir, ancak Java kodundan çağrı yaparken veya yansıma kullanırken yararlıdır.
// Both calls are equivalent
User.create("Bob")
User.Companion.create("Bob")
// Getting reference to companion object
val companion: User.Companion = User
Bir companion object bir ada sahip olabilir, bu da kod okunabilirliğini artırır ve anlamlı bir adla erişime izin verir. Factory, fabrika olarak kullanılan bir companion object için en yaygın 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")
}
}
// Access via Factory name
val response = HttpResponse.Factory.ok("data")
Adlandırılmış bir companion object, statik üyelerin amacını belgelemeye yardımcı olur. Yeniden düzenlemede, ad kodu kendi kendini belgeleyen hale getirir — geliştirici, Factory'nin HttpResponse örnekleri oluşturduğunu hemen görür.
Bir sınıf yalnızca bir companion object içerebilir. Bu, gruplama olmadan istediğiniz sayıda statik alan ve metot bildirebileceğiniz Java'dan temel bir farktır. Birden çok mantıksal statik üye grubuna ihtiyacınız varsa, companion olmadan iç içe object bildirimleri kullanın.
Resmi Kotlin belgelerine (Kotlin Docs, 2025) göre, tek companion object sınırlaması dil tasarımıyla motive edilmiştir: statik üyeler sınıfla sıkı bir şekilde bağlanmalıdır ve bir yoldaş nesne bu bağlantı için net bir sınır sağlar. Çok fazla statik üye varsa, bu sınıfı yeniden düzenleme sinyalidir.
Kotlin'de, arabirimler de companion object içerebilir. Bu, Java'da mümkün olmayan bir şekilde, doğrudan bir arabirim içinde statik metotlar ve sabitler tanımlamaya izin verir. Bu yaklaşım, genellikle arabirimle ilgili sabitleri veya fabrika metotlarını bildirmek için kullanılır.
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 örnekte, BASE_URL, TIMEOUT_MS ve create(), ApiService arabirimine aittir, uygulamalarına değil. Bu kullanışlıdır: tüm sabitler ve bir API hizmet örneği oluşturma mantığı tek bir yerde — arabirimin kendi içinde — bulunur.
Arabirim uygulamaları, companion object'in üyelerini devralmaz — bunlar yalnızca arabirim adı: ApiService.BASE_URL aracılığıyla çağrılır.
Java kodundan companion object metotları çağrılırken, varsayılan olarak dış sınıfın statik metotları olarak değil, iç içe Companion sınıfının metotları olarak erişilebilirler. Bunları Java için gerçek statik metotlar ve alanlar olarak dışa aktarmak için metotlar için @JvmStatic ve alanlar için @JvmField ek açıklamasını kullanın.
| Ek Açıklama | Uygulama | Java'da Sonuç |
|---|---|---|
| @JvmStatic | Companion object metotları | Statik metot: ClassName.method() |
| @JvmField | Companion object alanları | Statik alan: ClassName.field |
| const | İlkeller ve String | Satır içi sabit: derleyici değeri değiştirir |
| ek açıklama yok | Varsayılan metotlar/alanlar | 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"
}
}
// Called in Java as MathUtils.square(5), MathUtils.TAG
Java kodundan erişilebilir olması gereken tüm genel companion object metotları için @JvmStatic kullanılması önerilir. const yalnızca ilkel türlere ve String'e uygulanır — diğer türler için @JvmField kullanın.
Gerçek projelerde, companion object birkaç standart senaryo için kullanılır. Fabrika metotları en yaygın modeldir: farklı imzalara sahip birden çok kurucu yerine, companion object içinde adlandırılmış fabrika metotları kullanılır.
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 içindeki companion object, doğru genel türle bir Loading örneği oluşturan loading() fabrika metodu sağlar. Bu metot olmadan, doğrudan Loading() aracılığıyla bir örnek oluşturmanız gerekir, bu da iç uygulamayı açığa çıkarır.
companion object genellikle sınıfa özgü sabitleri depolamak için kullanılır. const val ile bildirilen sabitler derleme zamanında satır içine alınır ve çalışma zamanında sıfır ek yük sağlar.
class UserRepository {
companion object {
private const val TAG = "UserRepository"
private const val CACHE_SIZE = 100
private const val DEFAULT_PAGE_SIZE = 20
}
}
Sıkça Sorulan Sorular
Normal bir object, sınıftan bağımsız olarak var olan tam teşekküllü bir singleton'dur. companion object, üyeleri dış sınıf adı aracılığıyla çağrılan, sınıf içindeki bir object'tir. Bayt kodunda, companion object statik bir iç içe sınıf haline gelirken, normal bir object özerk bir singleton sınıfı haline gelir.
Hayır, companion object alt sınıflar tarafından miras alınmaz. B sınıfı A sınıfını genişletirse, B.method(), A sınıfının companion object'inden metodu çağırmaz — A.method() aracılığıyla çağırmanız gerekir. Bu, Java'daki statik metotların davranışıyla eşleşir.
Varsayılan olarak — ClassName.Companion.method() aracılığıyla. Statik bir metot olarak çağırmak için, companion object metoduna @JvmStatic ekleyin. Alanlar için, @JvmField kullanın veya ilkeller için const val ile bildirin.
Kotlin geliştiricileri, nesnelerle tek tip çalışma için static'ten vazgeçip companion object'i benimsemeye karar verdi. Java'daki static, OOP ilkelerini ihlal eder çünkü statik metotlar bir örneğe bağlı değildir. companion object, aktarılabilen, genişletme işlevleriyle genişletilebilen ve arabirimler uygulayabilen birinci sınıf bir nesnedir.
İlkeller ve String için const val kullanıldığında — sıfır ek yük, değer bayt koduna satır içine alınır. Metotlar için, metot inline olmadığı sürece ek yük yoktur. Çoğu durumda, companion object performans üzerinde ölçülebilir bir etki yaratmaz. Yalnızca Java'dan çağrılan genel API için @JvmStatic kullanın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun