Kotlin: How to use default parameters in functions and constructors

From time to time you can end up having functions or constructors where the amount of information available varies for different usages.

In these scenarios we want to be flexible enough that we can use the function even if we can't provide values for all the parameters.

In Java this is often solved by overloading the method — meaning that you have the same method defined several times with different parameter lists.

This quickly becomes verbose.

In Kotlin we can solve this in a simpler and more concise way, using default parameters.

This is as simple as it sounds. You basically define default values that will be used if a given parameter isn't provided during execution of the function.

Say we got a function that takes a first name and a last name, then prints a "hello" to the person.

fun sayHello(first: String, last: String) {  
    println("Hello $first $last")
}

Now, if we got all the parameters available, we can call it like any other function.

sayHello("John", "Doe")

//>Hello John Doe

Creating a function with default parameters

Now say the first name and last name isn't always provided.

In these scenarios we want to use "Mr" as the first name and an empty string as the last name instead.

Let's rewrite our sayHello function to to do this using default parameters.

fun sayHello(first: String = "Mr", last: String = "") {  
    println("Hello $first $last")
}

That's it! All we have to do is to define the default value to the parameters in the parameter list — in our scenario first: String = "Mr" and last: String = "".

So if a parameter is provided when the function is called, the default parameter will be ignored.

Now, if the parameters aren't provided, the default parameter value will be used.

Different ways of calling a function with default parameters

Now that we've refactored our function to have default parameters, let's take a look at the different ways we can call our function.

The thing is, it varies a bit how we provide our parameters dependent on which parameter we want to skip.

Providing no parameters

If we start by calling sayHello without any parameters, the greeting will be printed with both the default value for first name and last name.

sayHello()

//>Hello Mr

Providing only the first parameter

Now, it's not like we have to provide all parameters or no parameters — you can provide parts of the parameter list.

For instance, we can provide the first name, then leave out the last name.

sayHello("John")

//>Hello John

Easy right? Now how do we set only the last name? Because if we only bring one value like the example above it'll always be assigned to the first parameter.

Providing only second parameter

Now, if we only want to provide the last name we have to think a bit different.

The thing is, since the last name is the second parameter and we want to skip the first, we need to provide the last name as a named argument.

What this means is that we need to provide the name of the parameter as well as the value of the parameter.

This way Kotlin knows that the value should be assigned to the second parameter last and not to the first parameter as it would have been if we didn't provide the parameter name.

sayHello(last = "Doe")

//>Hello Mr Doe

Using default parameters in constructors

Using default parameters in a constructor is no different.

We use the same syntax and we'll see the same behavior.

To see how this works, let's first move our sayHello function into a class, then move the first and last parameter to the constructor.

class Person(val first: String = "Mr", val last: String = "") {  
  fun sayHello() {
    println("Hello ${first} ${last}")
  } 
}

If we now go through the same examples as with the function parameters, we'll see the same results.

Providing no parameters

Person().sayHello();

//>Hello Mr

As expected, we get the default value for both the first and last parameter.

Providing only first parameter

Person("John").sayHello()

//>Hello John

As you can see we now provide the first parameter during the object initialization, while the last parameter will use the default value.

Providing only second parameter

The last scenario we'll revisit is the one using a named argument to be able to skip the first parameter.

Person(last = "Doe").sayHello()

//>Hello Mr Doe

As you can see, default parameters can really clean up your code. It'll give you lots of flexibility without the need of boilerplate code.

Give it a go!