The Programmers Guide To Kotlin - Destructuring
Written by Mike James   
Monday, 14 September 2020
Article Index
The Programmers Guide To Kotlin - Destructuring
The Spread Operator

Destructuring  - it sounds like something to avoid, but in practice it is really useful. In this extract from The Programmers Guide To Kotlin by Mike James, we look at destructuring and the spread operator.

.

Programmer's Guide To Kotlin

Now Available as a Print Book

cover

You can buy it from: Amazon

Contents

Some Chapters Already Available On The Web

  1. What makes Kotlin Special (Book Only)
  2. The Basics: Variables, Primitive Types and Functions
  3. Control
  4. Strings and Arrays
  5. The Class & The Object
  6. Inheritance
  7. The Type Hierarchy 
            Extract  Type and its problems
            Extract  Smart Casts
  8. Generics
            Extract Basic Generics
            Extract Covariance & Contravariance
  9. Collections, Iterators, Sequences & Ranges
            Extract     Collections
            Extract Iterators & Sequences
  10. Advanced functions 
  11. Anonymous, Lamdas & Inline Functions
            Extract    Annoymous and Lambda Functions
            ExtractInline Functions
  12. Data classes, enums and destructuring
            Extract  Data Classes
            Extract      Enums & Sealed Classes 
            Extract 
         Delegated Properties 
            Extract      Destructuring  **NEW!**
  13. Exceptions, Annotations & Reflection
            Extract Exceptions
            Extract Annotation & Reflection 
  14. Working with Java
            Extract Using Swing  

In chapter but not in this extract

  • Data Classes
  • Equality
  • Enums
  • Sealed Classes – A Better Enum?
  • Delegated Properties

Destructuring

Destructuring is a sophisticated sounding name for a very simple idea. Sometimes you have a data structure with a number of elements or properties and you want to unpack these into a set of standalone variables. 

For example, if we have a data class:

data class MyDataClass(var name:String,var age:Int)

Then we can create an instance and use destructuring to pack the data into separate variables:

var myDataObject=MyDataClass("Mickey",89)
var (myName,myAge) = myDataObject
println(myName)
println(myAge)

The destructuring assignment:

var (myName,myAge) = myDataObject

is converted into:

var myName = myDataObject.component1()
var myAge = myDataObject.component2()

For a data object the operator methods component1, component2 and so on are automatically generated. This is the reason why if you take the data modifier from the start of the declaration you will get an error message as the class no longer has componentN methods.

Of course, you can add them manually:

class MyDataClass(var name:String,var age:Int){
   operator fun component1()=name
   operator fun component2()=age
}

In fact any class that has componentN operator methods can be used in a destructuring operation.

As well as assignment destructuring can be used in for loops.

For example:

val myList=listOf(
MyDataClass("Mickey",89),MyDataClass("Minnie",88))
    for ((name,age) in myList){
        println(name)
        println(age)
    }

As long as each element that the iterator returns supports destructuring, you can use this sort of for loop.

Destructuring can also allow a function to seem to return multiple values.

For example:

fun myFavouriteMouse():MyDataClass{
     return MyDataClass("Mickey",89)
 }

and you can now write:

var (myName,myAge)=myFavouriteMouse()

which looks as if myFavouriteMouse returns multiple values in the same way that you can in Python.

If you don't want to make use of a destructure value you can use an underscore to leave it out:

var (_,myAge)=myFavouriteMouse()

Finally, you can use destructuring in parameters of lambdas as long as the parameter type has componentN operator functions. Notice that this makes adding an extra set of parenthesis in a lambda an error. That is:

{ a,b-> statements that use a and b}
{(a,b)-> statements that use a and b}

are different in that the second one accepts a single parameter that can be destructured to give a and b.

For example:

 val myLambda= {(name,age):MyDataClass->
       println(name)
       println(age)
    }

This looks like a lambda that would accept two parameters, but because of destructuring it accepts a single instance of MyDataClass:

val myDataObject=MyDataClass("Mickey",89)
myLambda(myDataObject)

This works with any class that supports componentN operator methods.

kotlinlogo

 



Last Updated ( Monday, 14 September 2020 )