A singleton is a class which only allows one instance of itself to be created. This instance needs to also be globally accessible. Singletons are useful when exactly one object is needed to coordinate actions across the system.

Object Declarations

Kotlin provides an easy way to create singletons using the object declaration feature. For that, object keyword is used.

object SingletonExample {
    ... .. ...
    // body of class
    ... .. ...
}

The above code combines a class declaration and a declaration of a single instance SingletonExample of the class.

An object declaration can contain properties, methods and so on. However, they are not allowed to have constructors (which makes sense). Why?

Similar to objects of a normal class, you can call methods and access properties by using the . notation.

Example: Object Declaration

object Test {
    private var a: Int = 0
    var b: Int = 1

    fun makeMe12(): Int {
        a = 12
        return a
    }
}

fun main(args: Array<String>) {
    val result: Int

    result = Test.makeMe12()

    println("b = ${Test.b}")
    println("result = $result")
}

When you run the program, the output will be:

b = 1
result = 12

Object declaration can inherit from classes and interfaces in a similar way like normal classes.

Singletons and Dependency Injection

Object declarations can be useful sometimes. However, they are not ideal in large software systems that interact with many other parts of the system.

Kotlin object expressions

The object keyword can also be used to create objects of an anonymous class known as anonymous objects. They are used if you need to create an object of a slight modification of some class or interface without declaring a subclass for it. For example:

window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
        // ...
    }

    override fun mouseEntered(e: MouseEvent) {
        // ...
    }
})

(The example is taken from official Kotlin docs page.)

Here, an anonymous object is declared extending MouseAdapter class.The program overrides two MouseAdapter methods: mouseClicked() and mouseEntered().

If necessary, you can assign a name to the anonymous object and store it in a variable. For example,

val obj = object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
        // ...
    }

    override fun mouseEntered(e: MouseEvent) {
        // ...
    }
}

Example: Kotlin Object Expression

open class Person() {
    fun eat() = println("Eating food.")

    fun talk() = println("Talking with people.")

    open fun pray() = println("Praying god.")
}

fun main(args: Array<String>) {
    val atheist = object : Person() {
        override fun pray() = println("I don't pray. I am an atheist.")
    }

    atheist.eat()
    atheist.talk()
    atheist.pray()
}

When you run the program, the output will be:

Eating food.
Talking with people.
I don't pray. I am an atheist.

Here, anonymous object is stored in variable atheist which implements Person class with pray() method is overridden.

If you are implementing a class that has a constructor to declare an anonymous object, you need to pass appropriate constructor parameters. For example,

open class Person(name: String, age: Int) {

    init {
        println("name: $name, age: $age")
    }

    fun eat() = println("Eating food.")
    fun talk() = println("Talking with people.")
    open fun pray() = println("Praying god.")
}

fun main(args: Array<String>) {
    val atheist = object : Person("Jack", 29) {
        override fun pray() = println("I don't pray. I am an atheist.")
    }

    atheist.eat()
    atheist.talk()
    atheist.pray()
}

When you run the program, the output will be:

name: Jack, age: 29
Eating food.
Talking with people.
I don't pray. I am an atheist.

This tutorial was reposted from Programiz with additions