Object Declarations
Singleton is an object-oriented pattern where a class can have only one instance (object).
For example, you are working an application having SQL database backend. You want to create a connection pool to access the database while reusing the same connection for all clients. For this, you can create the connection through singleton class so that every client get the same connection.
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.
Recommended Reading: Dependency Injection & Singleton Design pattern
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.