You are currently viewing Kotlin Companion object

Kotlin Companion object

A companion object is a special type of object declaration that is tied to the Class. It’s similar to static members in other languages, but it can also implement interfaces, extend classes, and have its own properties and methods. Properties and methods can be directly accessed by the class name, without creating an instance of the class.

companion object can be declared inside a class by using the companion object keyword followed by braces, similar to defining a class. Here’s a basic example:

class MyClass {
    companion object {
        // properties and methods of the companion object
    }
}

Example Of companion object

class MyClass {
    companion object {
        const val constantValue = 42

        fun staticMethod() {
            println("This is a static method.")
        }
    }
}

In this example, Inside the companion object, you can define properties and methods just like you would in a regular class. You can access these members using the class name directly, without creating an instance of the class:

println(MyClass.constantValue)  // Accessing a property
MyClass.staticMethod()          // Calling a method

Implementing Interfaces/Extending Classes

Companion objects can also implement interfaces and extend classes,

Example 1: Companion Object Extending Regular Class :

Here is an example of companion object extending regular Class,

open class MyBaseClass {
    open val baseProperty: String = "Base Property"

    open fun baseMethod() {
        println("Base method")
    }
}

class MyClass {
    companion object : MyBaseClass() {
        // Additional properties and methods in the companion object
        val companionProperty = "Companion Property"

        override val baseProperty: String = "Overridden Base Property"

        override fun baseMethod() {
            println("Overridden base method in companion object.")
        }
        
        fun companionMethod() {
            println("Companion Method")
        }
    }
}

fun main() {
    // Accessing properties and methods from the companion object
    println(MyClass.baseProperty)
    MyClass.baseMethod()
    println(MyClass.companionProperty)
    MyClass.companionMethod()
}
Explanation:
  • MyBaseClass is a regular class with an open property and method.
  • MyClass has a companion object that extends MyBaseClass, inheriting its properties and methods.

Example 2: Companion Object Implementing Interface

Let’s take an example of companion object implementing Interface,

// Interface with abstract and non-abstract methods
interface MyInterface {
    // Abstract property
    val abstractProperty: String

    // Abstract method
    fun abstractMethod()

    // Non-abstract method
    fun nonAbstractMethod() {
        println("Non-abstract method in interface")
    }
}

// Class with a companion object implementing MyInterface
class MyClass {
    companion object : MyInterface {
        // Additional properties and methods in the companion object
        val companionProperty = "Companion Property"

        fun companionMethod() {
            println("Companion Method")
        }

        // Implementing the abstract property and method from MyInterface
        override val abstractProperty: String = "Implemented Abstract Property"

        override fun abstractMethod() {
            println("Implemented Abstract Method")
        }
    }
}

fun main() {
    // Accessing properties and methods from the companion object
    println(MyClass.companionProperty)  // Accessing property from the companion object
    MyClass.companionMethod()            // Calling method from the companion object

    // Implementing methods from MyInterface
    println(MyClass.abstractProperty)    // Accessing implemented abstract property
    MyClass.abstractMethod()             // Calling implemented abstract method
    MyClass.nonAbstractMethod()          // Calling non-abstract method from MyInterface
}

Here is the output of this program

Companion Property
Companion Method
Implemented Abstract Property
Implemented Abstract Method
Non-abstract method in interface

Explanation:

  • MyInterface is an interface with an abstract property, an abstract method, and a non-abstract method.
  • MyClass has a companion object that implements MyInterface, providing implementations for the abstract property and method, and it can also utilize the non-abstract method from the interface.

Use case of Companion object

Providing a way to associate static members with a class and encapsulate related functionality without the need for an instance of the class. Here are some common use cases for companion objects:

1. Static Members:

Companion objects are often used to declare static members (properties and methods) associated with a class. This can include constants, utility functions, or factory methods.

class MathUtils {
    companion object {
        const val PI = 3.14

        fun add(x: Int, y: Int): Int {
            return x + y
        }
    }
}
//usage
val sum = MathUtils.add(5, 7)
println("Sum: $sum")

2. Factory Methods:

Companion objects can be used to provide factory methods for creating instances of a class, allowing for more expressive and flexible object creation.

class Person private constructor(val name: String) {
    companion object {
        fun createPerson(name: String): Person {
            return Person(name)
        }
    }
}

3. Encapsulation:

If certain functionality is closely related to a class but doesn’t depend on instance-specific state, it can be encapsulated within the companion object.

class Logger private constructor() {
    companion object {
        fun log(message: String) {
            // Log the message
        }
    }
}

4. Constants and Configuration:

Companion objects is used for Storing constants, configuration parameters, and API endpoints.

class AppConfig {
    companion object {
        const val BASE_URL = "https://api.example.com"
        const val TIMEOUT = 5000
    }
}

5. Utility Methods:

Companion objects Encapsulating reusable utility methods for string manipulation, date formatting, etc.

class StringUtils {
    companion object {
        fun capitalize(input: String): String {
            return input.capitalize()
        }
    }
}
//usage
val capitalizedString = StringUtils.capitalize("hello")

6. Intent Extras and Keys:

Companion objects Standardizing Intent extras and keys for data transfer between components.

class IntentKeys {
    companion object {
        const val USER_ID = "user_id"
        const val USER_NAME = "user_name"
    }
}

7. Database Access and Queries:

Comapanion object is used for Managing database-related operations and obtaining database instances. Example:

class DatabaseHelper {
    companion object {
        fun getDatabaseInstance(context: Context): AppDatabase {
            // Code to get or create the database instance
        }
    }
}
Read: For more information about Companion object, you can explore the details provided in the official Kotlin documentation on Companion objects

Also Read :

Leave a Reply