Companion Objects
In this page:
class ClassName {
companion object {
const val CONSTANT = value
fun factory(): ClassName = ClassName()
}
}
ClassName.factory()
Declaring a Companion Object
A companion object block inside a class holds members accessible through the class name itself, without needing to create an instance first.
Example: Declaring a Companion Object
// Define a class `Circle`
class Circle(val radius: Double) {
companion object {
const val PI_APPROX = 3.14159
}
}
// Entry point: execution of the program starts here
fun main() {
// Print "Pi approximation: ${Circle.PI_APPROX}" to the console, with a trailing newline
println("Pi approximation: ${Circle.PI_APPROX}")
}
Login to try C/C++/Java/PHP code in the editor
Factory Functions in a Companion Object
A common pattern is defining a factory function inside a companion object that builds and returns instances, often used to hide or customize the details of construction.
Example: Factory Functions in a Companion Object
// Define a class `User`
class User private constructor(val name: String) {
companion object {
// Define the function `createGuest` with no parameters and returning a `User`
fun createGuest(): User = User("Guest")
}
}
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `guest`, set to `User.createGuest()`
val guest = User.createGuest()
// Print "User: ${guest.name}" to the console, with a trailing newline
println("User: ${guest.name}")
}
Login to try C/C++/Java/PHP code in the editor
Constants with const val
Companion objects are a natural place to define compile-time constants using const val, which are resolved directly at compile time and accessed through the class name.
Example: Constants with const val
// Define a class `Circle`
class Circle(val radius: Double) {
companion object {
const val UNIT = "cm"
}
fun describe() = "Radius: $radius $UNIT"
}
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `circle`, set to `Circle(5.0)`
val circle = Circle(5.0)
// Print `circle.describe()` to the console, with a trailing newline
println(circle.describe())
}
Login to try C/C++/Java/PHP code in the editor
Naming a Companion Object
A companion object can optionally be given a name, such as companion object Factory, which can then be used alongside the default class-name access for extra clarity.
Example: Naming a Companion Object
// Define a class `Widget`
class Widget private constructor(val id: Int) {
companion object Factory {
// Define the function `create` taking `id` and returning a `Widget`
fun create(id: Int): Widget = Widget(id)
}
}
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `widget`, set to `Widget.Factory.create(7)`
val widget = Widget.Factory.create(7)
// Print "Widget id: ${widget.id}" to the console, with a trailing newline
println("Widget id: ${widget.id}")
}
Login to try C/C++/Java/PHP code in the editor
- Confusing a companion object's members with static members in Java; Kotlin has no
statickeyword, companion objects are the closest equivalent. - Forgetting that a companion object is a real singleton object, and it can implement interfaces or have its own properties beyond simple factory functions.
- Trying to declare more than one companion object per class; only one companion object is allowed per class.
companion object { ... }inside a class declares members that belong to the class itself, not to individual instances.- Companion object members are accessed via
ClassName.member, similar to static members in other languages. - A companion object can be named, but if unnamed it defaults to the name
Companion. - Companion objects commonly hold factory functions, constants, or shared configuration related to the class.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: