Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 11

Default and Named Arguments

Recommended resources

Hello! Welcome to your next lesson in the "Learn Kotlin syntax" course.

In the last few lessons, we completed a deep dive into Kotlin's null-safety features, covering the safe call (?.), Elvis (?:), and the not-null assertion (!!) operators. Mastering these is fundamental to writing robust Kotlin code.

Today, we shift our focus to another area where Kotlin provides significant improvements in code clarity and conciseness over Java: function definitions. You'll learn how to define functions with default arguments and use named parameters when calling them. For a Java developer, this is a welcome departure from the verbosity of method overloading.

Learning Outcome: Define a function with default arguments and named parameters.


1. Reducing Boilerplate: Default Arguments

In Java, if you want to provide different ways to call a method with optional parameters, you typically resort to method overloading. You create multiple methods with the same name but different parameter lists.

For example, to create a user profile, you might have:

// In Java
public void createUser(String username) {
    createUser(username, "default_avatar.png");
}

public void createUser(String username, String avatarUrl) {
    // Logic to create user
    System.out.println("Creating user " + username + " with avatar " + avatarUrl);
}

This works, but it leads to boilerplate code where one overloaded method just calls another with a default value. Kotlin simplifies this dramatically with default arguments.

You can specify a default value for a parameter directly in the function signature. If an argument for that parameter is not provided in the function call, the default value is used.

// In Kotlin
fun createUser(username: String, avatarUrl: String = "default_avatar.png") {
    println("Creating user $username with avatar $avatarUrl")
}

fun main() {
    createUser("elena") // Uses the default avatar
    createUser("alex", "custom_avatar.jpg") // Overrides the default
}

This single function replaces both Java methods. It's cleaner and more maintainable.

The following short video from the Android Developers channel provides an excellent overview of this concept.

Don’t argue with default arguments - Kotlin Vocabulary

This video, 'Don’t argue with default arguments', quickly explains how default arguments reduce the need for function overloads in Kotlin.

Watch from the beginning to 01:00. Notice how it explicitly mentions replacing function overloads, a pattern you're familiar with from Java.

Now, let's see it in action with another practical example.

Kotlin Newbie To Pro - VARARG, DEFAULT AND NAMED PARAMETERS - Part 18

This video from Philipp Lackner demonstrates how to implement and use default arguments in a function.

Watch the segment on 'Default Arguments' from 06:46 to 09:48. The searchFor function example clearly shows how a function can be called with or without the optional searchEngine parameter.



2. Improving Readability: Named Arguments

Kotlin's second enhancement in this area is named arguments. When calling a function, you can explicitly name the parameters you are providing values for.

This offers two major benefits:

  1. Improved Readability: The function call becomes self-documenting. It's immediately clear what each value represents, which is especially helpful for functions with many parameters or parameters of the same type (e.g., configure(timeout: Int, retries: Int)).
  2. Argument Reordering: You are no longer required to pass arguments in the same order they were defined in the function signature.

Let's continue with the same video to see how this works.

Kotlin Newbie To Pro - VARARG, DEFAULT AND NAMED PARAMETERS - Part 18

The next segment of the same video introduces named parameters.

Watch from 09:48 to 11:19. Pay attention to how the arguments can be reordered when their names are specified.



3. The Power of Combination

The real power emerges when you combine default and named arguments. This combination allows you to skip any number of parameters with default values, regardless of their position, and provide values only for the ones you care about.

Consider a function for making a network request in a backend service:

fun makeApiRequest(
    endpoint: String, 
    method: String = "GET", 
    connectTimeout: Int = 10000, 
    readTimeout: Int = 10000,
    retries: Int = 3
) {
    println("Request: $method $endpoint, Retries: $retries, Read Timeout: $readTimeout")
}

Without named arguments, if you wanted to change retries but keep the default method and timeouts, you'd be stuck. You can't just skip parameters in the middle.

// This won't compile! How does the compiler know '5' is for 'retries'?
// makeApiRequest("users/123", 5) 

With named arguments, this becomes trivial and highly readable:

fun main() {
    // Call with only the required parameter
    makeApiRequest("products/456") 
    // Output: Request: GET products/456, Retries: 3, Read Timeout: 10000

    // Override the method
    makeApiRequest("products/456", method = "POST")
    // Output: Request: POST products/456, Retries: 3, Read Timeout: 10000

    // Override only the retries, skipping the parameters in between
    makeApiRequest(endpoint = "products/456", retries = 5)
    // Output: Request: GET products/456, Retries: 5, Read Timeout: 10000
}

This pattern is extremely common and useful, especially when configuring objects or calling functions with many optional settings.

To dive deeper into these concepts and see more examples, please read the following article.

Kotlin Default and Named argument

The article 'Kotlin Default and Named argument' from GeeksForGeeks provides a structured explanation with clear code examples for each scenario.

Read the sections 'Kotlin Default arguments' and 'Kotlin Named arguments'. The first section systematically shows what happens when you pass no, partial, or all arguments. The second section clearly explains how named arguments solve the ordering problem.

Finally, this pattern is frequently used with data class constructors, which you'll learn about later. The following resource gives a preview of such a real-world scenario.

Kotlin Default and Named Arguments

The article 'Kotlin Default and Named Arguments' from Kotlin Server Squad shows a practical example of using these features with a data class, which is very relevant for backend development.

Skim through the sections 'Default Arguments', 'Named Arguments', and pay special attention to the 'Real life example' with the Order data class. It demonstrates how these features make object instantiation clean and readable.



4. Code Exercise

Let's put this into practice. You'll create a flexible logging function.

  1. Open your IntelliJ IDEA project and create a new Kotlin file named Functions.kt.

  2. Inside the file, define a function named log. It should accept three parameters:

    • message: String (the log message)
    • level: String with a default value of "INFO"
    • tag: String with a default value of "Application"
    • The function body should simply print the parameters in a formatted string, like: [$level][$tag] $message
  3. Inside your main function, call your log function in the following ways to test its flexibility:

    • Call log with just a message: "User logged in successfully."
    • Call log with a message and a custom level: "Failed to connect to database.", level "ERROR". Use a named argument for the level.
    • Call log with a message and a custom tag: "Payment processed.", tag "Billing". Use a named argument for the tag.
    • Call log with all three arguments, but pass the tag before the level to confirm that named arguments allow reordering: "Initializing subsystems...", level "DEBUG", tag "Startup".
  4. Run your main function and verify that the output matches your expectations for each call.



Conclusion

You've now learned two powerful Kotlin features that lead to cleaner, more readable, and more flexible APIs. By favoring default and named arguments over method overloading, you can significantly reduce boilerplate and improve the developer experience of using your functions.

Key Takeaways:

  • Default Arguments allow you to specify default values for function parameters, reducing the need for extensive function overloading common in Java.
  • Named Arguments let you specify which parameter you're providing a value for, which improves code readability and allows you to pass arguments in any order.
  • Combining both features is a powerful pattern that allows you to selectively override default values for any parameter in a function call, making your code both concise and explicit.

Next Lesson Preview:

In our next lesson, we will explore another unique Kotlin feature: extension functions. You will learn how to add new functionality to existing classes—even ones you don't have the source code for—without using inheritance or wrapper classes. This is another tool that helps you write expressive and clean code.