Instruction

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Throughout this lesson, you’ll learn:

  • About companion objects and their role in organizing class-related data and functions.
  • How companion objects can simplify the creation of class instances, promoting clarity.
  • How to incorporate companion objects into code.

How Do You Declare a Companion Object?

Declaring and using a companion object is remarkably simple. You only need a companion object block of code for your class. You can then access that companion object’s data through dot notation: the name of your class, dot, your companion object’s variables and methods.

class Circle(val radius: Double) {
  companion object {
    const val PI = 3.14159
    fun calculateArea(radius: Double): Double {
      return PI * radius * radius
    }
  }
}
val area = Circle.calculateArea(5.0) 
println("The area of the circle is ${area}")
println("PI from companion object: ${Circle.PI}")

Companion Object Use Cases

Companion objects are that easy to use. However, don’t let their simplicity deceive you. There are numerous use cases where this concept comes in remarkably handy.

Factory Methods

Developers frequently leverage Kotlin companion objects for factory methods. Consider the following scenario. Suppose you’re writing a blogging app with three different types of users:

sealed class User(val username: String)
class AdminUser(username: String) : User(username)
class EditorUser(username: String) : User(username)
class ContributorUser(username: String) : User(username)
class UserManager {
  companion object {
    fun createUser(username: String, userType: String): User {
      return when (userType.toLowerCase()) {
        "admin" -> AdminUser(username)
        "editor" -> EditorUser(username)
        else -> ContributorUser(username)
      }
    }
  }
}

Data Validation

Data validation is another significant use case for Kotlin companion objects.

class Address private constructor(
  private val street: String, 
  private val city: String,
  private val zipCode: String
) {
  companion object { 
    fun createAddress(street: String, city: String, zipCode: String): Address? {
      if (!AddressValidationAPI.isValidAddress(street, city, zipCode)) {
        return null  // Address failed validation
      }
      return Address(street, city, zipCode)
    }
  }
}

Helper Methods

Another everyday use case for companion objects involves creating utility or helper functions. Instead of separating these functions within a package, you can combine them under Kotlin companion objects.

class StringUtils {
  companion object {
    fun normalizeSpaces(text: String): String {
      return text.trim().replace(Regex("\\s+"), " ") 
    }
  }
}
See forum comments
Download course materials from Github
Previous: Introduction Next: Demo