Idiomatic Kotlin: Object and Singleton

Tompee Balauag
Familiar Android
Published in
3 min readJul 10, 2018
“Blue sand falls in an hourglass on a rocky beach” by Aron on Unsplash

This article is a part of the Idiomatic Kotlin series. The complete list is at the bottom of the article.

In this article, we will be discussing about the the object keyword and singletons in Kotlin, and its limitations.

What is a Singleton and an object (in Kotlin)?

The singleton pattern restricts the instantiation of a class to a single object. It is useful in cases wherein you only need a single object to contain a global state.

To create a singleton, one has to make sure that

  1. Only one instance can exist
  2. It has global access

This is generally achieved by

  1. Declaring all constructors private
  2. Access is through static methods that ensures a single instance

An object in Kotlin (among its many purposes) is both a class definition and an instantiation of single instance combined. It is a first class language support for singletons.

Motivation

Let’s see how to create a simple singleton in Java.

Three things to note.

  1. Constructors should be private to prevent instantiation outside of the class
  2. Interface is through a public static method to provide global access
  3. Thread-safe access

Notice the amount of boilerplate code. Imagine having to write them for every singleton class that you have.

How to create a Singleton?

One of the many uses of the object keyword in Kotlin is to create a class with just a single instance.

To create a singleton, just define the class as an object instead. Objects can inherit other classes and implement interfaces as well. It can also contain an init block. You can reference and object via its class name and access all of its public methods and properties just like a normal object.

Object under the hood

Let us try to decompile an object similar to the one above (this time with init block statements and a property).

We can see that it is eerily similar to our simple Java singleton declaration at the start. Therefore our assumptions toward object and singleton holds true.

Notice that the initialization happens on a static block. In Java, static blocks are executed on class loading time. This approach guarantees that lazy-loading and thread-safety.

Considerations and Limitations

A major thing to consider when using object is that it does not have constructors. This is because they are instantiated on class reference. Therefore, dependency injection at instantiation is not straightforward (constructor injection is already impossible). To achieve this, you have to default back to the original way singletons are created (by using classes and companion objects).

Singleton pattern and object is therefore only good for instances with little to no dependencies. On large software projects with large dependencies, it is arguably better to employ dependency injection for scoping and lifecycle management of regular classes instead.

Check out the other articles in the idiomatic kotlin series. The sample source code for each article can be found here in Github.

  1. Extension Functions
  2. Sealed Classes
  3. Infix Functions
  4. Class Delegation
  5. Local functions
  6. Object and Singleton
  7. Sequences
  8. Lambdas and SAM constructors
  9. Lambdas with Receiver and DSL
  10. Elvis operator
  11. Property Delegates and Lazy
  12. Higher-order functions and Function Types
  13. Inline functions
  14. Lambdas and Control Flows
  15. Reified Parameters
  16. Noinline and Crossinline
  17. Variance

--

--