Companion Objects

Another use of the object keyword is for a companion of a class. A companion is a singleton, associated with the class, whose functions somewhat fill the role that static methods do in Java. In fact, if you set up those functions the right way, they can be called from Java as static methods.

Declaring and Using a Companion Object

A companion object is simply an object, nested inside of a class, prefixed with the companion keyword:

class Thingy {
  companion object {
    fun doSomething() {
      println("Ummm... is this something?")
    }
  }

  // TODO add other properties and functions
}

fun main() {
  Thingy.doSomething()
}

Then, other parties can call the companion object’s functions as if they were “static” functions on the enclosing class (e.g., Thingy.doSomething().

Why Bother?

It is entirely possible that you are unimpressed by this. After all, we can have top-level functions in Kotlin:

fun doSomething() {
  // TODO
}

doSomething()

However, companion objects have one key advantage: they have access to private functions and properties of their enclosing class. So, this works:

class Thingy {
  private val count = 1

  companion object {
    fun doSomething(thingy: Thingy) {
      println(thingy.count)
    }
  }

  // TODO add other properties and functions
}

fun main() {
  Thingy.doSomething(Thingy())
}

Even though count is private, doSomething() can still reference it, since doSomething() is a part of the Thingy implementation.

By contrast, a top-level function cannot reference private functions and properties, so this fails with a compile error:

class Thingy {
  private val count = 1
}

fun doSomething(thingy: Thingy) {
  println(thingy.count)
}

Naming a Companion Object

Sometimes, you will see a companion object have a name, though probably not one named after a companion, as we have here:

class Thingy {
  private val count = 1

  companion object AmyPond {
    fun doSomething(thingy: Thingy) {
      println(thingy.count)
    }
  }

  // TODO add other properties and functions
}

fun main() {
  Thingy.doSomething(Thingy())
}

This has limited impact on your Kotlin code — you still call functions on the class as before. It does have an impact if you are going to try using the companion object functions from Java, as we will explore later in the book.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.