Blog / July 13, 2018 / 3 mins read / By Suneet Agrawal

Companion object in Kotlin

Unlike Java or C#, Kotlin doesn’t have static members or member functions. Kotlin recommends to simply use package-level functions instead.

If you need to write a function that can be called without having a class instance but needs access to the internals of a class, you can write it as a member of a companion object declaration inside that class. By declaring a companion object inside our class, you’ll be able to call its members with the same syntax as calling static methods in Java/C#, using only the class name as a qualifier.

How should I declare a companion object inside a class?

Add companion keyword in front of object declaration.

class EventManager {

    companion object FirebaseManager {
     
    }  
}
val firebaseManager = EventManager.FirebaseManager

Optionally, you can even remove the companion object name also. In that case the name Companion will be used.

class EventManager {

    companion object {
       
    }
}
val firebaseManager = EventManager.Companion

Let’s take an example of Singleton class where a single instance of the class exists and we get that instance using getInstance static method.

//Java code
public class EventManager {

    private static EventManager instance;

    private EventManager() {

    }

    public static EventManager getManagerInstance() {
        if (instance == null) {
            instance = new EventManager();
        }

        return instance;
    }

    public boolean sendEvent(String eventName) {
        Log.d("Event Sent", eventName);
        return true;
    }
}

Now when we try to implement the same class in the Kotlin, the private static instance and the managerInstance property will be moved to companion object. Rest of the code remains the same.

//Kotlin code
class EventManager {

    private constructor() {
    }

    companion object {
        private lateinit var instance: EventManager

        val managerInstance: EventManager
            get() {
                if (instance == null) {
                    instance = EventManager()
                }

                return instance
            }
    }

    fun sendEvent(eventName: String): Boolean {
        Log.d("Event Sent", eventName)
        return true;
    }
}

And how I use the sendEvent method?

  1. When you name the companion object as FirebaseManager
val firebaseManager = EventManager.FirebaseManager
firebaseManager.managerInstance.sendEvent("some event")
//or
EventManager.FirebaseManager.managerInstance.sendEvent("Some event")
  1. When you didn’t name the companion object
val firebaseManager = EventManager.Companion
firebaseManager.managerInstance.sendEvent("some event")
// or
EventManager.Companion.managerInstance.sendEvent("Some event")

Please keep in mind, even though the members of companion object look like static members in other languages, at runtime those are still instance members of real objects, and can, for example, implement interfaces.

However, if you use the@JvmStatic annotation, you can have members of companion objects generated as real static methods and fields on the JVM.

//Kotlin code
interface EventManagementInterface {
    fun someMethod()
}

class EventManager {

    companion object FirebaseManager : EventManagementInterface {
        
        override fun someMethod() {
            
        }
    }
}

A companion object is initialized when the corresponding class is loaded (resolved), matching the semantics of a Java static initializer. Means that the companion object will be initialized even before calling the constructor of that class as similar to Java static initializer.

Comments