Effective Kotlin Item 48: Consider using object declarations
When you have a class without any instance-specific state, you can turn it into an object declaration to define a singleton. This means not defining a constructor and using the
object keyword instead of
class. We reference the singleton object using the name of the object declaration.
Object declarations are useful to limit the number of created objects. This is especially useful for classes that are created many times in your projects, like events or markers. Thanks to object declarations, we can be sure that they have only one instance.
It’s a bit more challenging when you want to turn a class that has some generic parameter types, like
DeleteAll in the following example, into an object declaration:
In such cases, it is popular to use the pattern called Covariant Nothing Object36. To use it, we need to make the type parameter of the supertype class covariant (so, use the
out modifier next to
T in the
StoreMessage declaration), then use
Nothing as a type argument for the object declaration:
Nothing is a subtype of all types in Kotlin, and
StoreMessage is covariant,
StoreMessage<Nothing> is a subtype of all
StoreMessage<T> types. This means that
DeleteAll is a subtype of
StoreMessage<T> for all
This pattern is used in many projects and libraries, including Kotlin stdlib. For instance,
EmptyList is an object declaration that is a subtype of
List<Nothing>; as a result, it is a subtype of all
List<T> types. This way, there is only one instance of an empty list in the whole application.
- To define singletons, turn classes without an instance-specific state into object declarations.
- Use the covariant nothing object pattern to turn classes with generic type parameters into object declarations.
I defined and described this in detail in the book Advanced Kotlin.