🎓 A1Learner
🔍
0 of 37 lessons completed

Kotlin Objects and Companions

An object declaration creates one shared instance under a fixed name. A companion object groups members that belong to a class itself rather than to one instance.

One counter shared by every call

Counter is a single object, so its count keeps its value between calls. Writing a new value into count changes what later calls see.

object Counter {
    var count: Int = 0
    fun bump() {
        count++
    }
}
fun main() {
    Counter.bump()
    Counter.bump()
    println(Counter.count)
    Counter.count = 10
    Counter.bump()
    println(Counter.count)
}

An object expression for one use

The object expression implements Speaker for this one value. No class name and no separate declaration are needed.

interface Speaker {
    fun speak(): String
}
fun main() {
    val parrot = object : Speaker {
        override fun speak(): String = "Squawk"
    }
    println(parrot.speak())
}

A companion object factory

The constructor of User is private, so code outside the class cannot call it. The companion object factory functions can call it and hand back finished instances.

class User private constructor(val name: String) {
    companion object {
        fun guest(): User = User("Guest")
        fun from(raw: String): User = User(raw.trim())
    }
}
fun main() {
    println(User.guest().name)
    println(User.from("  Ana  ").name)
}

A companion counter of instances

Each Token init block adds one to the counter in the companion object. After three instances, the counter reads three.

class Token(val label: String) {
    companion object {
        var created: Int = 0
    }
    init {
        created++
    }
}
fun main() {
    val first = Token("one")
    val second = Token("two")
    val third = Token("three")
    println(first.label)
    println(second.label)
    println(third.label)
    println(Token.created)
}

Example

object Settings {
    var volume: Int = 5
    fun describe(): String = "Volume is $volume"
}
fun main() {
    println(Settings.describe())
    Settings.volume = 8
    println(Settings.describe())
    Settings.volume = 2
    println(Settings.describe())
}

Key points

  • Code reaches an object through its name, with no constructor call.
  • State stored in an object persists across calls because there is only one instance.
  • An object expression creates an unnamed object for a single use.
  • An object expression can implement an interface for that single use.
  • A companion object sits inside a class, and its members are called through the class name.
  • A factory function in a companion object can call a private constructor of its class.

In this example, Settings is one object that holds a volume value. Each describe call reads the value stored in that same object. Writes between the calls change the line that the next call prints.

Note

A companion object can also hold a counter that the class updates each time an instance is created.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Kotlin Playground

Exercise

How many instances does an object declaration create?