Kotlin Companion Objects: More than just Singleton functionality

Home » Kotlin » Kotlin Companion Objects: More than just Singleton functionality

The Companion Objects in Kotlin offer more than just Singleton functionality. In this Kotlin tutorial, We will explore the power packed features of Kotlin Companion Object.

Understanding Companion Objects in Kotlin

In Kotlin, a Companion Object represents an object tied to a class, enabling the definition of static members within the class. It acts as a container for elements that one should access directly on the class itself, rather than on instances of the class. You declare the Companion Object inside the class using the companion keyword, and it shares the same name as its containing class.

Kotlin Companion Objects: More than just Singleton functionality

Here’s a simple example:

companion object {
        fun showMessage() = "Hello Companion Object❤️"
    }

Program Example in Kotlin:

Open the Kotlin Playground and Write the following program:

fun main()
{
  println(Demo.showMessage())

}

class Demo{
    companion object {
        fun showMessage() = "Hello Companion Object❤️"
    }
}

Output

Hello Companion Object❤️

In this example, the Demo has a Companion Object containing a function showMessage(). The function can be called directly on the class, like this:

Demo.showMessage()

In Kotlin, the syntax resembles Java’s static methods where you use the class name to call object members. If you intend to use a companion object in Kotlin, opt for a package-level function instead.

Companion Object with Name

class Counter {
    companion object StartNow{
        fun start(n: Int){
            for(i in 1 .. n)
            {
                println(i)
            }
        }
    }
}

Program:

class Counter {
    companion object StartNow{
        fun start(n: Int){
            for(i in 1 .. n)
            {
                println(i)
            }
        }
    }
}

fun main()
{
 
  Counter.start(5)

}

Output

1
2
3
4
5

In Kotlin, you can define a class and its companion object. The companion object’s name can be omitted. Within the companion object, you can define methods. To call the companion object method, you simply use the class name as the qualifier.

Singleton Pattern with Companion Objects

Companion Objects are a convenient way to implement the Singleton pattern. When a function or a property is declared inside a Companion Object, it behaves like a static member and is associated with the class itself rather than any specific instance.

class Logger private constructor() {
    companion object {
        val instance: Logger by lazy { Logger() }
    }

    fun log(message: String) {
        println("[LOG] $message")
    }
}

fun main()
{
    val log = Logger.instance.log("Error")
}

Output

[LOG] Error

In this example, the Logger class has a private constructor to prevent external instantiation. The Singleton instance of Logger is created lazily using the by lazy initialization inside the Companion Object. Now, you can access the Logger instance anywhere in the application without creating multiple instances.

Companion Objects as Factories

Companion Objects can also act as factories to create instances of their containing class.


data class Point(val x: Int, val y: Int) {
    companion object {
        fun create(x: Int, y: Int): Point {
            return Point(x, y)
        }
    }
}

fun main()
{
    val obj = Point.create(56,67)
    println(obj)
}

In this example, the Point class has a private constructor, but it provides a create() function inside the Companion Object to create instances of Point. Now, you can create Point objects using the factory method without exposing the constructor.

Extension Functions with Companion Objects

Kotlin allows you to define extension functions on the Companion Object, further enhancing the flexibility and readability of your code. Extension functions are a powerful feature of Kotlin that allows you to add new functionality to existing classes without modifying their source code.

class MyClass {
    companion object {
        // ...
    }
}

fun MyClass.Companion.extensionFunction() {
    println("Extension function called!")
}

How to call it?

 val ext = MyClass.extensionFunction()
 println(ext)

Kotlin Companion Objects offer a plethora of powerful features, from implementing the Singleton pattern to acting as factories and supporting extension functions.

Happy Coding!

You may also like...