Companion Object

اگر بخواهیم فیلد یا خاصیتی ایجاد کنیم که در همه نمونه‌های کلاس قابل دسترسی باشد از کلمه کلیدی companion استفاده می‌کنیم. کلمه کلیدی companion برای اعضای داده‌ای و خاصیت‌هایی به کار می‌رود که می‌خواهند در همه نمونه‌های کلاس تقسیم شوند. وقتی که یک متد یا خاصیت به صورت companion تعریف شود، می‌توانید آنها را بدون ساختن نمونه‌ای از شی، فراخوانی کنید. برای استفاده از این کلمه کلیدی ابتدا یک بلوک به صورت زیر تعریف کرده :

companion object
{
    // some code
}

و سپس در داخل این بلوک، متغیر، فیلد، متد و … را که می‌خواهید بدون ایجاد نمونه از کلاس به آنها دسترسی داشته باشید را در داخل این بلوک می‌نویسید. به چند مثال توجه کنید :

  1: class SampleClass
  2: {
  3:     companion object
  4:     {
  5:         var CompanionMessage: String = "This is the static message!"
  6:     }
  7: }
  8: 
  9: fun main(args: Array<String>)
 10: {
 11:     println(SampleClass.CompanionMessage)
 12: }
This is the companion message!

در مثال بالا یک متغیر به نام CompanionMessage (خط 5) تعریف کرده‌ایم. مقدار متغیرCompanionMessage در همه نمونه‌های کلاس SampleClass قابل دسترسی است. برای فراخوانی یک متد، خاصیت و یا یک متغیر، به سادگی می‌توان نام کلاس و بعد از آن علامت دات ( . ) و در آخر نام متد یا خاصیت را نوشت. این موضوع را می‌توان در خط (11) مشاهده کرد. مشاهده می‌کنید که لازم نیست هیچ نمونه‌ای از کلاس ایجاد شود. یکی دیگر از کاربردهای این کلمه کلیدی در شمارش اشیاء است. به مثال زیر توجه کنید :

  1: class SampleClass 
  2: {
  3:     init 
  4:     {
  5:         println("Number is : " + number++)
  6:     }
  7: 
  8:     companion object 
  9:     {
 10:         var number = 1
 11:     }
 12: }
 13: 
 14: fun main(args: Array<String>)
 15: {
 16:     val Sample1 = SampleClass()
 17:     val Sample2 = SampleClass()
 18:     val Sample3 = SampleClass()
 19: }
Number is : 1
Number is : 2
Number is : 3

همانطور که در خط 10 کد بالا مشاهده می‌کنید یک متغیر با مقدار اولیه 1 ایجاد کرده‌ایم و در داخل بلوک companion object در خط 5 ابتدا مقدار آن را چاپ و سپس یک واحد به آن اضافه کرده‌ایم. حال در خطوط 18-16 سه شیء از روی کلاس SampleClass ایجاد می‌کنیم. همانطور که در خروجی مشاهده می‌کنید با هر بار ایجاد شی یک بار سازنده کلاس فراخوانی و در نتیجه مقدار متغیر چاپ می‌شود. متغیرهایی که در داخل بلوک companion تعریف می شوند، مقدار قبلی خود را حفظ می‌کنند. و از این خاصیت در مثال بالا برای شمارش اشیاء ساخته شده از کلاس استفاده کرده‌ایم. اگر با جاوا آشنا باشید، می‌توانید Companion Object در کاتلین را معادل متدهای static در جاوا در نظر بگیرید، گرچه چگونگی کارکرد آنها از نظر داخلی با یک دیگر متفاوت می‌باشد. Companion Object ها می‌توانند به اعضای Private یک کلاس نیز دسترسی داشته باشند.