Using Default and Named Arguments in Kotlin

Kayvan Kaseb
Software Development
5 min readAug 30, 2022
The picture is provided by Unsplash

As a matter of fact, the overabundance of overloaded methods in some classes can be considered as one of the problematic issues in Java programming. Obviously, this leads to duplication and boilerplate code. To address this issue effectively, Kotlin uses default and named arguments in practice. Moreover, these approaches can boost the readability of code considerably. This essay aims to discuss some main concepts in using default and named arguments in Kotlin for Android developers.

Introduction and Overview

Essentially, one of the typical problems in Java is the overabundance of overloaded methods in some classes. The overloads can be provided for some reasons, such as backward compatibility, for convenience of API users, or for other reasons. Nevertheless, the final result is the same in these cases: duplication and boilerplate code. The parameter names and types are often repeated, and you must repeat most of the documentation in every overload. In the meantime, if you call an overload that eliminate some parameters, it is s not always obvious which values are used for them practically. In fact, you can often avoid creating this issue in Kotlin since you can be able to define default values for parameters in a function declaration. Besides, if you call a function, you can name one or more of its arguments. This can be useful when a function has a number of arguments because it would be difficult to relate a value with an argument, in particular, if you have a boolean or null value. In Kotlin, named arguments work well with default parameter values.

Kotlin Default Arguments

To diminishes the number of overload in your functions, Kotlin offers an advanced feature to assign default argument (parameter) in a function definition. Therefore, function parameters can have default values, which are used when you skip the corresponding argument. A default value is typically determined using = after the type. For example, the default value for the first parameter is used in calling:

fun doPrint(
first: Int = 0,
second: Int,
third: Boolean = true
)
{ println("The output parameters are first = $first, second = $second, third = $third") }

fun main() {
doPrint(second = 1)
doPrint(second = 1, third = true)
}

For instance, the cnTimeout and enRetry parameters have been declared as default arguments as follows:

fun connect(urlConnection: String, cnTimeout: Int = 2500, enRetry: Boolean = false) {
println("The output parameters are urlConnecion = $urlConnection, cnTimeout = $cnTimeout, enRetry = $enRetry")
}
fun main() {
connect("http://www.SampleCode.com")
connect("http://www.SampleCode.com", 4500)
connect("http://www.SampleCode.com", false) // Compile Error!
connect("http://www.SampleCode.com", enRetry = false)
}

So, as the cnTimeout and enRetry parameters are declared with default values, you can skip them in the function call. The results for these calls will be:

The output parameters are urlConnecion = http://www.SampleCode.com, cnTimeout = 2500, enRetry = false The output parameters are urlConnecion = http://www.SampleCode.com, cnTimeout = 4500, enRetry = false

However, if you want to skip just only the middle argument, you will deal with a compile error as follows:

The boolean literal does not conform to the expected type Int

This means if an argument with a default value is eliminated in function call, all following arguments have to be passed as named arguments. Furthermore, you will pass it either as a named argument or outside the parentheses if the last one after default parameters is a lambda expression. The following example uses both default values for first and second arguments:

fun doPrint(
first: Int = 3,
second: Int = 2,
third: () -> Unit,
)
{ println("The output parameters are first = $first, second = $second, third = $third") }

fun main() {
doPrint(third = { println("Kotlin Programming") })
doPrint{ println("Kotlin Programming") }
}

To consider this matter in details, you can use Java decompiled code to see what the compiler generates for you: Tools -> Kotlin -> Show Kotlin Bytecode then you should press the Decompile button.

Here, the question is that what happens when we want to override a function, specially with default arguments? For instance, the output for the following code will be:

Kotlin Programming
Java

open class BaseClass { 
open fun doPrint(language: String = "Java") {
// ...
}
}
class SampleClass : BaseClass() {
override fun doPrint(language: String) {
println(" $language")
}
}

fun main () {
val sample = SampleClass()
sample.doPrint("Kotlin Programming")
sample.doPrint()
}

Obviously, the sample parameter in the overridden doPrint function uses the default value declared in the base class function. However, it is not possible for an overriding function to specify default values for their parameters.

Kotlin Named Arguments

As mentioned earlier, if you call a function, you can have an opportunity to define one or more of its arguments. This can be useful when a function has a lot of arguments as it would be hard to relate a value with an argument, in particular if you face with a boolean or null value in your code. This leads to make the function calls more readable. In other words, a named argument is an argument in which you can be able to specify the name of argument in the function call. The name declared to argument of function call checks the name in the function definition and assign to it. For instance, if we call doPrint(‘c’), we will del with a compile error as mentioned before. Thus, to address this issue properly, we should use named argument as follows:

fun doPrint(num:Int= 10, sample: Char ='d'){  
print("$num and $sample")
}
fun main () {
doPrint(sample='z')
}

Then, 10 and z will be printed as output. This means you can skip specific arguments with default values. Nevertheless, after the first skipped argument, you have to name all further argument. Another significant point is that when you apply named arguments in a function call, you can modify the order they are listed as you like. Eventually, you cannot utilize named arguments while calling methods written in Java, like methods from the JDK and the Android framework.

Unfortunately, you can’t use named arguments when calling methods written in Java, including methods from the JDK and the Android framework. Storing parameter names in .class files is supported as an optional feature only starting with Java 8, and Kotlin maintains compatibility with Java. As a result, the compiler can’t recognize the parameter names used in your call and match them against the method definition.

In Conclusion

Initially, one of the common problems in Java is the overabundance of overloaded methods in some classes. This leads to duplication and boilerplate code. To tackle this issue efficiently, Kotlin use default and named arguments in reality. This article discussed some key concepts in using default and named arguments for Android developers based on JetBrains and Google documentations and resources.

--

--

Kayvan Kaseb
Software Development

Senior Android Developer, Technical Writer, Researcher, Artist, Founder of PURE SOFTWARE YAZILIM LİMİTED ŞİRKETİ https://www.linkedin.com/in/kayvan-kaseb