Objects, Companions & Singletons
The object keyword: instant singletons
Sometimes you want exactly one instance of something for the whole app — a configuration holder, a logger. In Kotlin, object creates a singleton in one line; the language guarantees only one instance exists.
object AppConfig {
const val VERSION = "1.0.0"
var darkMode = false
fun toggleTheme() { darkMode = !darkMode }
}
// use it directly — no 'new'
println(AppConfig.VERSION)
AppConfig.toggleTheme()
Companion objects: “static” members
Kotlin has no static keyword. Instead, members that belong to the class itself (not an instance) go in a companion object — a great place for factory methods and constants.
class User private constructor(val name: String) {
companion object {
const val MAX_NAME_LENGTH = 30
fun create(name: String): User {
require(name.length <= MAX_NAME_LENGTH)
return User(name)
}
}
}
val u = User.create("Anand") // factory method
println(User.MAX_NAME_LENGTH)
Here the constructor is private, so the only way to build a User is through the controlled create factory — a common, clean pattern.
Anonymous objects
You can also create a one-off object on the spot, often to implement an interface (like a click listener):
val listener = object : Clickable {
override fun onClick() = println("clicked once")
}
object vs class
- class — a blueprint you instantiate many times.
- object — a single, ready-made instance (singleton).
- companion object — class-level members shared by all instances.
Common mistakes
- Storing lots of changing state in a global
object— singletons with mutable state can cause hard-to-trace bugs. In Android, prefer dependency injection. - Using a companion object for things that should be top-level functions.
Summary:objectgives you a one-line singleton;companion objectreplaces Java’s static members and is perfect for factory methods and constants.