Companion object در Kotlin: چیست، نحو و کاربرد

نویسنده: IT Sectr منتشر شده: 2026-06-21 زمان مطالعه: 9 دقیقه

companion object — مکانیزم زبان Kotlin است که کلمه کلیدی static از Java را برای اعلام اعضای ایستای کلاس جایگزین می‌کند. در Kotlin static داخلی وجود ندارد — در عوض از اعلان object با اصلاح‌کننده companion در داخل کلاس استفاده می‌شود. به گفته JetBrains, 2025، companion object امکان فراخوانی متدها و ویژگی‌ها را از طریق نام کلاس فراهم می‌کند که آن‌ها را به معادل کامل اعضای ایستا در اکوسیستم Java تبدیل می‌کند.

نکات اصلی

  • companion object — اعلان object در داخل کلاس با کلمه کلیدی companion، جایگزین Java static
  • اعضای ایستا از طریق نام کلاس بدون ایجاد نمونه قابل دسترسی هستند: ClassName.method()
  • companion object نام‌دار امکان نام‌گذاری object را برای کد خواناتر فراهم می‌کند
  • اینترفیس‌ها در Kotlin نیز می‌توانند companion object با پیاده‌سازی متدها داشته باشند
  • @JvmStatic — annotation برای صدور متدهای companion object به عنوان متدهای static واقعی در Java

companion object در Kotlin چیست؟

companion object — نوع خاصی از object declaration در زبان Kotlin است که با کلمه کلیدی companion علامت‌گذاری می‌شود. این امکان را فراهم می‌کند تا اعضایی را اعلام کنید که به کلاس تعلق دارند نه به نمونه‌های آن — یعنی اعضای ایستا در اصطلاحات Java. برخلاف Java که در آن static اصلاح‌کننده برای فیلدها و متدهای جداگانه است، در Kotlin اعضای ایستا در داخل یک object همراه گروه‌بندی می‌شوند.

هر کلاس در Kotlin می‌تواند دقیقاً یک companion object داشته باشد. اعضای این object از طریق نام کلاس بدون ایجاد نمونه قابل دسترسی هستند: MyClass.method(). در عین حال از نظر بایت‌کد، companion object به یک کلاس داخلی جداگانه کامپایل می‌شود و متدهای آن با استفاده از annotation @JvmStatic به متدهای ایستای کلاس خارجی تبدیل می‌شوند.

بر اساس Google I/O 2024، companion object به الگوی اصلی برای متدهای کارخانه‌ای، ثابت‌ها و توابع کمکی در برنامه‌های مدرن Android با Kotlin تبدیل شده است. توسعه‌دهندگان آن را به جای کلاس‌های کمکی با توابع بسته‌ای انتخاب می‌کنند، زیرا companion object ارتباط منطقی با کلاس مالک را حفظ می‌کند.

از companion object برای گروه‌بندی زمینه ایستا — ثابت‌ها، کارخانه‌ها، متدهای کمکی که منطقاً به کلاس مربوط هستند اما نیاز به نمونه ندارند — استفاده کنید.

نحو companion object: اعلان و دسترسی

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

kotlin
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 برای primitives و String.

دسترسی ضمنی و صریح از طریق Companion

اگر companion object نام ندارد، می‌توان از طریق نام خودکار Companion به آن دسترسی داشت: User.Companion.TABLE_NAME. در عمل این به ندرت لازم است، اما هنگام فراخوانی از کد Java یا هنگام استفاده از reflection مفید است.

kotlin
// هر دو فراخوانی معادل هستند
User.create("Bob")
User.Companion.create("Bob")

// دریافت ارجاع به companion object
val companion: User.Companion = User

companion object نام‌دار و ویژگی‌ها

companion object می‌تواند نام داشته باشد که خوانایی کد را بهبود می‌بخشد و امکان دسترسی به آن را با یک نام قابل فهم فراهم می‌کند. Factory — رایج‌ترین نام برای companion object است که به عنوان کارخانه استفاده می‌شود.

kotlin
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 برای هر کلاس

یک کلاس فقط می‌تواند یک companion object داشته باشد. این تفاوت اساسی با Java است که در آن می‌توان هر تعداد فیلد و متد ایستا بدون گروه‌بندی اعلام کرد. اگر چندین گروه منطقی از اعضای ایستا نیاز است، از object declarations تو در تو بدون companion استفاده کنید.

بر اساس مستندات رسمی Kotlin (Kotlin Docs, 2025)، محدودیت یک companion object با طراحی زبان مرتبط است: اعضای ایستا باید با کلاس ارتباط تنگاتنگ داشته باشند و یک object همراه مرز روشن این ارتباط را فراهم می‌کند. اگر اعضای ایستا بیش از حد زیاد باشند — این سیگنالی برای بازسازی کلاس است.

Companion object در اینترفیس‌ها

در Kotlin، اینترفیس‌ها نیز می‌توانند companion object داشته باشند. این امکان تعریف متدها و ثابت‌های ایستا را مستقیماً در داخل اینترفیس فراهم می‌کند که در Java امکان‌پذیر نیست. این رویکرد اغلب برای اعلام ثابت‌های مرتبط با اینترفیس یا متدهای کارخانه‌ای استفاده می‌شود.

kotlin
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.

@JvmStatic و @JvmField: سازگاری با Java

هنگام فراخوانی متدهای companion object از کد Java، آن‌ها به طور پیش‌فرض به عنوان متدهای کلاس داخلی Companion قابل دسترسی هستند، نه به عنوان متدهای ایستای کلاس خارجی. برای صدور آن‌ها به عنوان متدها و فیلدهای static واقعی برای Java، از annotation @JvmStatic برای متدها و @JvmField برای فیلدها استفاده کنید.

Annotationکاربردنتیجه در Java
@JvmStaticمتدهای companion objectمتد ایستا: ClassName.method()
@JvmFieldفیلدهای companion objectفیلد ایستا: ClassName.field
constانواع اولیه و Stringثابت درون‌خطی: کامپایلر مقدار را جایگزین می‌کند
بدون annotationمتدها/فیلدهای پیش‌فرضCompanion.method() / Companion.field
kotlin
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 برای چندین سناریوی استاندارد استفاده می‌شود. متدهای کارخانه‌ای — رایج‌ترین الگو: به جای سازنده‌های متعدد با امضاهای مختلف، از متدهای کارخانه‌ای نام‌دار در companion object استفاده می‌شود.

kotlin
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 در مرحله کامپایل درج می‌شوند که سربار صفر در زمان اجرا ایجاد می‌کند.

kotlin
class UserRepository {
    companion object {
        private const val TAG = "UserRepository"
        private const val CACHE_SIZE = 100
        private const val DEFAULT_PAGE_SIZE = 20
    }
}

سوالات متداول

تفاوت companion object با object معمولی در Kotlin چیست؟

ordinary object — یک singleton کامل است که مستقل از کلاس وجود دارد. companion object — object در داخل کلاس است که اعضای آن از طریق نام کلاس خارجی فراخوانی می‌شوند. در بایت‌کد، companion object به یک کلاس داخلی ایستا تبدیل می‌شود و object معمولی به یک کلاس singleton مستقل تبدیل می‌شود.

آیا می‌توان companion object را به ارث برد؟

خیر، companion object توسط زیرکلاس‌ها به ارث برده نمی‌شود. اگر کلاس B از کلاس A ارث‌بری کند، B.method() متدی را از companion object کلاس A فراخوانی نمی‌کند — باید از طریق A.method() دسترسی داشت. این رفتار مطابق با متدهای ایستا در Java است.

چگونه companion object را از کد Java فراخوانی کنیم؟

به طور پیش‌فرض — از طریق ClassName.Companion.method(). برای فراخوانی به عنوان متد ایستا، @JvmStatic را به متد companion object اضافه کنید. برای فیلدها از @JvmField استفاده کنید یا آن‌ها را با const val برای انواع اولیه اعلام کنید.

چرا Kotlin کلمه کلیدی static ندارد؟

توسعه‌دهندگان Kotlin تصمیم گرفتند به نفع companion object از static صرف‌نظر کنند تا کار با object‌ها یکپارچه باشد. static در Java اصول OOP را نقض می‌کند زیرا متدهای ایستا با نمونه مرتبط نیستند. companion object — یک object درجه یک است که می‌توان آن را منتقل کرد، با توابع توسعه‌دهنده گسترش داد و اینترفیس‌ها را پیاده‌سازی کرد.

آیا companion object بر عملکرد تأثیر می‌گذارد؟

هنگام استفاده از const val برای انواع اولیه و String — سربار صفر، مقدار در بایت‌کد درج می‌شود. برای متدها سرباری وجود ندارد اگر متد inline نباشد. در بیشتر موارد، companion object تأثیر قابل اندازه‌گیری بر عملکرد ندارد. از @JvmStatic فقط برای API عمومی که از Java فراخوانی می‌شود استفاده کنید.

خلاصه

  • companion object — مکانیزم Kotlin برای اعلام اعضای ایستای کلاس، جایگزین Java static
  • یک companion object برای هر کلاس — تمام عناصر ایستا را در یک object همراه گروه‌بندی می‌کند
  • دسترسی از طریق نام کلاس: ClassName.method() یا ClassName.Companion.method()
  • @JvmStatic و @JvmField اعضا را به عنوان متدها و فیلدهای static واقعی برای Java صادر می‌کنند
  • const val برای انواع اولیه و String — مقدار را بدون سربار در مرحله کامپایل درج می‌کند
  • اینترفیس‌ها نیز از companion object برای ثابت‌ها و متدهای کارخانه‌ای پشتیبانی می‌کنند
  • companion object نام‌دار خوانایی کد را بهبود می‌بخشد و هدف اعضای ایستا را خود-مستندساز می‌کند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید