Skip to main content

Kotlin Default Arguments

Introduction

When writing functions in programming, we often face situations where we want to provide flexibility in how a function can be called. In many languages, this requires creating multiple function versions (overloads) for different parameter combinations. Kotlin offers a simpler solution with default arguments, which allow you to specify default values for parameters, making them optional when calling the function.

In this tutorial, we'll explore Kotlin's default arguments feature, how to use it effectively, and how it helps create cleaner, more maintainable code.

The Basics of Default Arguments

What Are Default Arguments?

Default arguments are predefined values for function parameters. When a caller doesn't provide a value for a parameter with a default argument, the default value is automatically used.

Let's start with a simple example:

kotlin
fun greet(name: String, greeting: String = "Hello") {
println("$greeting, $name!")
}

// Usage examples
fun main() {
greet("Alice") // Output: Hello, Alice!
greet("Bob", "Welcome") // Output: Welcome, Bob!
}

In this example, greeting has a default value of "Hello". When we call greet("Alice"), we're only providing the name parameter, so the function uses the default value for greeting.

Multiple Default Arguments

You can define multiple parameters with default values:

kotlin
fun displayUserInfo(
name: String,
age: Int = 30,
isAdmin: Boolean = false,
department: String = "General"
) {
println("Name: $name")
println("Age: $age")
println("Admin: $isAdmin")
println("Department: $department")
}

fun main() {
// Using all defaults except name
println("--- User 1 ---")
displayUserInfo("John")

// Specifying some arguments
println("--- User 2 ---")
displayUserInfo("Sarah", 28, department = "Engineering")
}

Output:

--- User 1 ---
Name: John
Age: 30
Admin: false
Department: General
--- User 2 ---
Name: Sarah
Age: 28
Admin: false
Department: Engineering

Named Arguments with Default Values

Default arguments become even more powerful when combined with named arguments. This allows you to specify only the parameters you need, regardless of their order:

kotlin
fun createProfile(
name: String,
email: String = "",
age: Int = 0,
isPremium: Boolean = false
) {
println("Creating profile:")
println("- Name: $name")
println("- Email: ${if (email.isNotEmpty()) email else "Not provided"}")
println("- Age: ${if (age > 0) age else "Not provided"}")
println("- Account type: ${if (isPremium) "Premium" else "Standard"}")
}

fun main() {
// Only required parameter
createProfile("Alex")

// Using named arguments to provide specific parameters
createProfile(
name = "Maria",
isPremium = true,
email = "[email protected]"
)
}

Output:

Creating profile:
- Name: Alex
- Email: Not provided
- Age: Not provided
- Account type: Standard
Creating profile:
- Name: Maria
- Email: [email protected]
- Age: Not provided
- Account type: Premium

Real-World Use Cases for Default Arguments

1. UI Component Configuration

Default arguments are great for configuring UI components:

kotlin
fun createButton(
text: String,
width: Int = 100,
height: Int = 40,
isEnabled: Boolean = true,
backgroundColor: String = "#FFFFFF",
textColor: String = "#000000"
) {
println("Button created:")
println("- Text: $text")
println("- Size: ${width}x$height")
println("- Enabled: $isEnabled")
println("- BG Color: $backgroundColor")
println("- Text Color: $textColor")
}

fun main() {
// Basic button
createButton("OK")

// Custom button
createButton(
text = "Submit",
width = 200,
backgroundColor = "#0066CC",
textColor = "#FFFFFF"
)
}

2. HTTP Client Configuration

Default arguments can simplify API client configuration:

kotlin
fun fetchData(
url: String,
method: String = "GET",
headers: Map<String, String> = mapOf("Content-Type" to "application/json"),
timeout: Int = 30000,
retries: Int = 3
) {
println("Fetching data from: $url")
println("- Method: $method")
println("- Headers: $headers")
println("- Timeout: $timeout ms")
println("- Retries: $retries")
// Actual implementation would go here
}

fun main() {
// Basic fetch with defaults
fetchData("https://api.example.com/data")

// POST request with custom timeout and no retries
fetchData(
url = "https://api.example.com/create",
method = "POST",
timeout = 5000,
retries = 0
)
}

3. Configuration Builder Pattern

Default arguments are useful in builder patterns:

kotlin
class DatabaseConfig(
val host: String,
val port: Int,
val username: String,
val password: String,
val database: String,
val maxConnections: Int,
val timeout: Int,
val ssl: Boolean
)

fun createDatabaseConfig(
host: String = "localhost",
port: Int = 5432,
username: String = "admin",
password: String = "",
database: String,
maxConnections: Int = 10,
timeout: Int = 30000,
ssl: Boolean = false
): DatabaseConfig {
return DatabaseConfig(host, port, username, password, database, maxConnections, timeout, ssl)
}

fun main() {
// Creating minimal configuration
val defaultConfig = createDatabaseConfig(database = "app_data")

// Custom configuration
val prodConfig = createDatabaseConfig(
host = "db.production.example.com",
database = "production_data",
username = "app_service",
password = "secure_password",
ssl = true,
maxConnections = 50
)

println("Default config host: ${defaultConfig.host}")
println("Production config host: ${prodConfig.host}")
}

Default Arguments vs. Method Overloading

In many object-oriented languages like Java, method overloading is used to provide multiple versions of a function. Kotlin's default arguments offer several advantages:

  1. Reduced code duplication: You write one function instead of multiple overloaded versions
  2. More readable code: Intent is clearer with named arguments
  3. Easier maintenance: Changes only need to be made in one place

Consider this comparison:

Java-style Overloading:

kotlin
// Java-style overloading
fun connect(host: String, port: Int, username: String, password: String, database: String) {
// Implementation with all parameters
}

fun connect(host: String, port: Int, username: String, password: String) {
connect(host, port, username, password, "default_db")
}

fun connect(host: String, port: Int, username: String) {
connect(host, port, username, "", "default_db")
}

fun connect(host: String, port: Int) {
connect(host, port, "admin", "", "default_db")
}

fun connect(host: String) {
connect(host, 5432, "admin", "", "default_db")
}

Kotlin Default Arguments:

kotlin
fun connect(
host: String,
port: Int = 5432,
username: String = "admin",
password: String = "",
database: String = "default_db"
) {
println("Connecting to $database on $host:$port as $username")
// Implementation with all parameters
}

fun main() {
connect("db.example.com")
connect("db.example.com", 3306)
connect("db.example.com", 3306, "user")
connect("db.example.com", username = "user", database = "custom_db")
}

The Kotlin version is much more concise and maintainable!

Important Considerations

1. Default Arguments are Evaluated at Call Time

Default values are computed during the function call, not during function definition:

kotlin
var counter = 0

fun incrementingDefault(value: Int = counter++) {
println("value = $value, counter = $counter")
}

fun main() {
incrementingDefault() // value = 0, counter = 1
incrementingDefault() // value = 1, counter = 2
incrementingDefault() // value = 2, counter = 3
}

2. Default Arguments and Java Interoperability

When calling Kotlin functions with default arguments from Java, you must provide all arguments, as Java doesn't understand Kotlin's default arguments. To solve this, use the @JvmOverloads annotation:

kotlin
@JvmOverloads
fun formatName(
firstName: String,
lastName: String,
middleName: String = "",
title: String = ""
): String {
val fullName = buildString {
if (title.isNotEmpty()) append("$title ")
append(firstName)
if (middleName.isNotEmpty()) append(" $middleName")
append(" $lastName")
}
return fullName
}

This generates Java-friendly overloaded methods.

Summary

Kotlin's default arguments feature offers significant advantages for writing clean, flexible, and maintainable code:

  • Reduces the need for function overloading
  • Makes code more readable with named arguments
  • Provides sensible defaults while allowing customization
  • Simplifies API design and usage
  • Works well with Kotlin's other features like named arguments

As you continue developing in Kotlin, default arguments will become one of your favorite features for creating flexible and user-friendly APIs.

Exercises

To practice using default arguments in Kotlin:

  1. Create a function calculatePrice that computes the final price of a product with parameters for base price, tax rate (default 0.1), discount (default 0), and shipping (default 5.99).

  2. Write a function to create formatted text with parameters for text content, font size (default 12), color (default "black"), and style options like bold and italic (default false).

  3. Implement a logging function with parameters for message, level (default "INFO"), timestamp (default current time), and tags (default empty list).

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)