Illustration of mobile phone with Kotlin and Android logos around it.

Breaking down destructuring declarations

Kotlin Vocabulary — destructuring

Florina Muntenescu
Android Developers

--

Sometimes you just want to break down one object that contains multiple fields to initialize several separate variables. To achieve this, you can use Kotlin’s destructuring declarations. Read on to find out how to use this feature, what Kotlin types offer it by default, how to implement it in your own classes or for classes that you don’t control but you think would benefit from destructuring and how everything works under the hood.

Usage

Destructuring declarations allows us to define local values/variables as such:

It’s a convenient way to work with data coming from functions or collections:

By default, all data classes support destructuring.

You can decide to only use a subset of variables from your class’s fields:

Destructuring doesn’t allow you to pick exactly which fields you want to use; it will always use the first x fields, where x is the number of variables you declare. The downside of this is that it’s easy to make mistakes. For example the following snippet might provide an unexpected result:

val (name, rating) = goodDoggo

The rating value will actually hold the value of goodDoggo.breed. You will get a warning saying: “Variable name ‘rating’ matches the name of a different component” and a suggestion to rename the rating to breed. As this is only in the IDE and not a compile warning it might be easy to miss.

Using a wrong destructuring variable declaration

If you only need a subset of non-consecutive fields, use _ for those you’re not interested in, Kotlin will just skip them. The example above becomes:

val (name, _, rating) = goodDoggo

Under the hood

Let’s take a look at a decompiled data class to see what’s going on. In this post we’ll only focus on the functions generated for destructuring. For more information on data classes in general, stay tuned for a future post.

To see the Java decompiled code, go to Tools -> Kotlin -> Show Kotlin Bytecode then press the Decompile button.

We see that functions called componentN are generated for every property declared in the primary constructor, where N is the index of the field in the primary constructor.

Implementing destructuring

As we’ve seen, destructuring relies on componentN functions. So if you want to add the destructuring functionality to a class that doesn’t support it, then just implement the corresponding componentN operator function. Make sure you prefix them with the operator keyword.

Implementing destructuring for classes you don’t own

Kotlin allows you to implement destructuring for classes you don’t own via extension functions. For example, Map.Entry is just an interface and by default it does not support destructuring. To overcome this, component1() and component2() functions were created, that return the key and value of Map.Entry.

Conclusion

Use destructuring whenever you need to unpack the fields of an object to values/variables. Under the hood destructuring is implemented by providing componentN operator functions, so you can provide those yourself for classes that you think benefit from this functionality.

--

--