Companion Object In Kotlin

  3 mins read  

Companion Object

This article will try to explain companion objects in Kotlin and also provide examples for how they can be accessed via Java. Before companion objects can be explained, it is best to first explain the object declaration in Kotlin.

Object

The object declaration in Kotlin is similar to Scala, it is used to declare a Singleton. In the following example a KotlinObject is declared, and an assert is used to verify that only one instance exists.

object KotlinObject {
    fun hello() {
        print("hello!")
    } 
}

val firstObject = KotlinObject
val secondObject = KotlinObject

assert(firstObject === secondObject)

Companion Object

A companion object is the declaration of an object inside a class. The companion object can be accessed similarly to the way static fields and methods are accessed in Java, the class is used as a qualifier. The following is a declaration of a companion object in the Person class.

class Person(val firstName: String, val lastName: String) {
    companion object {
        fun defaultPerson() = Person("Jane", "Smith") 
    }
}

val person = Person.defaultPerson()

Since Kotlin is compiled into bytecode, companion objects can be accessed in Java. The following example demonstrates the accessing of a companion object in Java. Since there wasn’t a name provided for the Person companion object, the default name of Companion is provided to the object. This means the companion object can be accessed by using the qualifier Person.Companion.

var person = Person.Companion.defaultPerson();

Companion objects are similar to normal objects, so they can implement interfaces. The following example declares a Factory interface and the Car companion object implements the Factory.

interface Factory<T> {
    fun create() : T
}

class Car(val make: String, val model: String) {
    companion object CarFactory: Factory<Car> {
        override fun create(): Car = Car("Honda", "Civic")
    }
}

val car = Car.create()

Since the companion object was named as CarFactory, the companion object is accessed via Car.CarFactory in Java.

var car = Car.CarFactory.create();

Some JVM libraries (e.g., JUnit) depend on static methods. To support these libraries Kotlin has a @JvmStatic annotation. The @JvmStatic annotation instructs the Kotlin compiler to generate real static fields and methods.

class Dog(val breed: String) {
    companion object{
        @JvmStatic
        fun defaultDog() = Dog("mutt")
    }
}

In the following Java example, the companion object’s method that was annotated with @JvmStatic can be accessed as a traditional static method.

var dog = Dog.defaultDog();

I hope this post helped provide insight into objects and companion objects in Kotlin. If you want to experiment with any of the examples, they can be found here in GitHub.