How to write more idiomatic constructors in Kotlin

Marc Guilera
CasumoTech
Published in
3 min readAug 28, 2019

Introduction

Kotlin is a modern object-oriented language which has been gaining traction year over year. While it’s earned a lot of fans in the Android world, it has also been successfully used in many applications from the frontend to the backend.

Below, I will make the case that replacing constructors for static factory methods can make your code more flexible and idiomatic, resulting in a more consistent, clean and readable API.

In this article, I will focus on constructors and extension methods which are features present in Kotlin as well as in many other languages so the ideas should be applicable there as well.

Consider a simple class representing a user in the system.

The problem

Classes can have one primary constructor and as many secondary constructors as we need to allow consumers to create instances with different arguments.

Having many constructors in one class might seem okay but when writing APIs it is important to consider readability and predictability. In other words, our interfaces should be self-explanatory to consumers of the API.

Constructors have two sneaky properties:

  • Unlike regular functions, they have no name.
  • They can only return the instance of the class they belong to.

Continuing with the User class example, the application has grown and we need to instantiate users from JSON and another type of user. One could add secondary constructors to our class:

This solution would work but it has two issues:

  • It is not clear from the API that a constructor with one String argument expects a JSON string in a set format.
  • We have added unnecessary coupling with FacebookUser, an external entity, directly in our own model.

While this is a very simple example it’s easy to see how it can get increasingly out of hand pretty quickly.

The solution

Some inspiration

There is nothing wrong with borrowing ideas from other languages, right? Dart, a cool language open-sourced by Google, solves the aforementioned issues elegantly through the factory keyword.

What’s interesting about factory methods in Dart is that they can be named and, since they are regular methods, can return any implementation of the class in question. This allows the developer to create specialized implementations of an interface and hide them from the consumer.

But this is a Kotlin article, right?

Of course, we can achieve this in Kotlin through static functions. As a matter of fact, libraries do this all the time. ie: listOf, Mono.fromCallable, etc.

Now we can fix the User class using companion methods:

Calling User.fromJson(string) or User.fromFacebookUser(facebookUser) is much clearer than User(string) or User(facebookUser). However, the coupling with FacebookUser is still there. Kotlin’s extension methods are of great help with that.

The Facebook logic can now be moved elsewhere without compromising the idiomatic API shown earlier. A good place would be in a dedicated Facebook package where other Facebook-specific logic lives.

This approach provides the flexibility to create new constructors as the application needs evolve. It also allows hiding away the instantiation logic from the consumer so the returned object can, for example, come from a cache or a singleton where the consumer shouldn’t be aware of that fact but it is acceptable to share the instance between calls.

Final remarks

We have learned how to create more idiomatic constructors by not using constructors with Kotlin or any language with similar features which provides some benefits:

  • Idiomatic and meaningful constructors.
  • Freedom to return specialized subclasses of an interface.
  • Decoupling intent from the instantiation logic.

It is important to note that this in no way aids with creating complex objects which several dependencies. In such a case, a regular factory class with the appropriate DI would be a much better approach.

--

--

Marc Guilera
CasumoTech

Worked as a Software Engineer in San Francisco, Malta and now Barcelona mainly using C# and Java but I’m always up for new challenges.