companion object Kotlin زبان کا ایک طریقہ کار ہے جو کلاس کے جامد اراکین کے اعلان کے لیے Java کے static کلیدی لفظ کو تبدیل کرتا ہے۔ Kotlin میں بلٹ ان static نہیں ہے — اس کے بجائے، کلاس کے اندر companion modifier کے ساتھ object اعلان استعمال ہوتا ہے۔ JetBrains, 2025 کے مطابق، companion object کلاس کے نام کے ذریعے طریقوں اور خصوصیات کو کال کرنے کی اجازت دیتا ہے، جو انہیں Java ماحولیاتی نظام میں جامد اراکین کا مکمل ہم پلہ بناتا ہے۔
اہم نکات
companion object Kotlin میں object اعلان کی ایک خاص قسم ہے جسے companion کلیدی لفظ سے نشان زد کیا جاتا ہے۔ یہ ان اراکین کا اعلان کرنے کی اجازت دیتا ہے جو کلاس کی مثالوں کے بجائے کلاس سے تعلق رکھتے ہیں — یعنی Java کی اصطلاحات میں جامد اراکین۔ Java کے برعکس، جہاں static انفرادی فیلڈز اور طریقوں کے لیے ایک modifier ہے، Kotlin میں جامد اراکین ایک ہم نشین آبجیکٹ کے اندر گروپ کیے جاتے ہیں۔
Kotlin میں کوئی بھی کلاس بالکل ایک companion object رکھ سکتی ہے۔ اس آبجیکٹ کے اراکین مثال بنائے بغیر کلاس کے نام کے ذریعے قابل رسائی ہیں: MyClass.method()۔ بائٹ کوڈ کے لحاظ سے، companion object ایک علیحدہ اندرونی کلاس میں مرتب ہوتا ہے، اور @JvmStatic تشریح استعمال کرنے پر اس کے طریقے بیرونی کلاس کے جامد طریقے بن جاتے ہیں۔
Google I/O 2024 کے مطابق، companion object Kotlin میں لکھی گئی جدید Android ایپلیکیشنز میں فیکٹری طریقوں، مستقلات اور معاون افعال کے لیے مرکزی نمونہ بن گیا ہے۔ ڈویلپر پیکیج سطحی افعال والی افادیت کلاسوں کے بجائے اسے منتخب کرتے ہیں کیونکہ 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 }
}
// Access via class name
val table = User.TABLE_NAME
val user = User.create("Alice")
اوپر کی مثال میں، TABLE_NAME اور create() User.TABLE_NAME اور User.create() کے ذریعے قابل رسائی ہیں۔ ابتدائی مستقلات کے لیے const modifier پر توجہ دیں — یہ مرتب وقت پر قدر کو شامل کرنے کی ضمانت دیتا ہے، جو ابتدائی اقسام اور String کے لیے Java static final سے ملتا جلتا ہے۔
اگر companion object کا کوئی نام نہیں ہے، تو اسے خودکار نام Companion: User.Companion.TABLE_NAME کے ذریعے رسائی حاصل کی جا سکتی ہے۔ عملی طور پر یہ شاذ و نادر ہی ضروری ہے، لیکن Java کوڈ سے کال کرتے وقت یا reflection استعمال کرتے وقت مفید ہے۔
// Both calls are equivalent
User.create("Bob")
User.Companion.create("Bob")
// Getting reference to 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")
}
}
// Access via Factory name
val response = HttpResponse.Factory.ok("data")
نام والا companion object جامد اراکین کے مقصد کو دستاویز کرنے میں مدد کرتا ہے۔ تنظیم نو میں، نام کوڈ کو خود دستاویزی بناتا ہے — ڈویلپر فوراً دیکھتا ہے کہ Factory HttpResponse کی مثالیں بناتا ہے۔
ایک کلاس صرف ایک companion object رکھ سکتی ہے۔ یہ Java سے ایک بنیادی فرق ہے، جہاں آپ گروپنگ کے بغیر کسی بھی تعداد میں جامد فیلڈز اور طریقے اعلان کر سکتے ہیں۔ اگر جامد اراکین کے متعدد منطقی گروپوں کی ضرورت ہو، تو companion کے بغیر اندرونی object اعلانات استعمال کریں۔
سرکاری 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 کے ذریعے کال کیے جاتے ہیں۔
Java کوڈ سے companion object کے طریقوں کو کال کرتے وقت، ڈیفالٹ طور پر وہ بیرونی کلاس کے جامد طریقوں کے بجائے اندرونی Companion کلاس کے طریقوں کے طور پر قابل رسائی ہوتے ہیں۔ انہیں Java کے لیے حقیقی جامد طریقوں اور فیلڈز کے طور پر برآمد کرنے کے لیے، طریقوں کے لیے @JvmStatic اور فیلڈز کے لیے @JvmField تشریح استعمال کریں۔
| تشریح | اطلاق | Java میں نتیجہ |
|---|---|---|
| @JvmStatic | Companion object کے طریقے | جامد طریقہ: ClassName.method() |
| @JvmField | Companion object کے فیلڈز | جامد فیلڈ: ClassName.field |
| const | ابتدائی اقسام اور String | ان لائن مستقل: مرتب کنندہ قدر کو بدل دیتا ہے |
| بغیر تشریح | ڈیفالطریقے/فیلڈز | 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
تمام عوامی companion object طریقوں کے لیے @JvmStatic استعمال کرنے کی سفارش کی جاتی ہے جو 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>()
NetworkResult میں companion object ایک فیکٹری طریقہ loading() فراہم کرتا ہے جو صحیح generic قسم کے ساتھ Loading کی مثال بناتا ہے۔ اس طریقے کے بغیر، آپ کو براہ راست Loading() کے ذریعے مثال بنانا ہوگی، جو اندرونی نفاذ کو ظاہر کرتا ہے۔
companion object اکثر کلاس کے مخصوص مستقلات کو ذخیرہ کرنے کے لیے استعمال ہوتا ہے۔ const val کے ساتھ اعلان کردہ مستقلات مرتب وقت پر شامل ہو جاتے ہیں، جو رن ٹائم پر صفر اضافی بوجھ فراہم کرتے ہیں۔
class UserRepository {
companion object {
private const val TAG = "UserRepository"
private const val CACHE_SIZE = 100
private const val DEFAULT_PAGE_SIZE = 20
}
}
اکثر پوچھے گئے سوالات
عام object ایک مکمل singleton ہے جو کلاس سے آزادانہ طور پر موجود ہوتا ہے۔ companion object کلاس کے اندر ایک object ہے جس کے اراکین بیرونی کلاس کے نام کے ذریعے کال کیے جاتے ہیں۔ بائٹ کوڈ میں، companion object ایک جامد اندرونی کلاس بن جاتا ہے، جبکہ عام object ایک خود مختار singleton کلاس بن جاتا ہے۔
نہیں، companion object ذیلی کلاسوں کو وراثت میں نہیں ملتا۔ اگر کلاس B کلاس A کو بڑھاتی ہے، تو B.method() کلاس A کے companion object سے طریقہ نہیں بلائے گا — آپ کو A.method() کے ذریعے کال کرنا ہوگا۔ یہ Java میں جامد طریقوں کے رویے سے مطابقت رکھتا ہے۔
ڈیفالٹ طور پر — ClassName.Companion.method() کے ذریعے۔ اسے جامد طریقہ کے طور پر کال کرنے کے لیے، companion object کے طریقے میں @JvmStatic شامل کریں۔ فیلڈز کے لیے، @JvmField استعمال کریں یا انہیں ابتدائی اقسام کے لیے const val کے ساتھ اعلان کریں۔
Kotlin کے ڈویلپرز نے اشیاء کے ساتھ یکساں کام کے لیے static کو چھوڑ کر companion object اپنانے کا فیصلہ کیا۔ Java میں static OOP اصولوں کی خلاف ورزی کرتا ہے کیونکہ جامد طریقے کسی مثال سے منسلک نہیں ہوتے۔ companion object ایک first-class آبجیکٹ ہے جسے منتقل کیا جا سکتا ہے، توسیعی افعال سے بڑھایا جا سکتا ہے اور انٹرفیس لاگو کیے جا سکتے ہیں۔
ابتدائی اقسام اور String کے لیے const val استعمال کرتے وقت — صفر اضافی بوجھ، قدر بائٹ کوڈ میں شامل ہو جاتی ہے۔ طریقوں کے لیے، جب تک طریقہ inline نہ ہو کوئی اضافی بوجھ نہیں ہے۔ زیادہ تر معاملات میں، companion object کارکردگی پر کوئی قابل پیمائش اثر نہیں ڈالتا۔ صرف Java سے کال کیے جانے والے عوامی API کے لیے @JvmStatic استعمال کریں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں