Kotlin Default Arguments

Default arguments let you assign a fallback value to a function parameter. When you call the function without passing that argument, Kotlin uses the default. This reduces the need to write multiple versions of the same function.

Without Default Arguments (the problem)

// Three separate functions doing the same thing differently
fun sendEmail(to: String, subject: String, body: String) { }
fun sendEmailNoSubject(to: String, body: String) { }
fun sendEmailNoBody(to: String, subject: String) { }
// Messy! Lots of repeated logic.

With Default Arguments (the solution)

fun sendEmail(
    to: String,
    subject: String = "No Subject",
    body: String = "No Content"
) {
    println("To: $to")
    println("Subject: $subject")
    println("Body: $body")
    println("─────────────")
}

fun main() {
    sendEmail("alice@mail.com")
    sendEmail("bob@mail.com", "Meeting Notes")
    sendEmail("carol@mail.com", "Invoice", "Please find attached.")
}

Output:

To: alice@mail.com
Subject: No Subject
Body: No Content
─────────────
To: bob@mail.com
Subject: Meeting Notes
Body: No Content
─────────────
To: carol@mail.com
Subject: Invoice
Body: Please find attached.
─────────────

How Defaults Are Applied


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

Call                          │ Result
──────────────────────────────┼──────────────────────
greet()                       │ Hello, Guest!
greet("Maria")                │ Hello, Maria!
greet("Maria", "Hi")          │ Hi, Maria!

Defaults with Any Type

fun createAccount(
    username: String,
    role: String = "viewer",
    isActive: Boolean = true,
    loginCount: Int = 0
) {
    println("User: $username | Role: $role | Active: $isActive | Logins: $loginCount")
}

fun main() {
    createAccount("admin_user", "admin")
    createAccount("reader123")
    createAccount("dev_user", "developer", false)
}

Output:

User: admin_user | Role: admin | Active: true | Logins: 0
User: reader123 | Role: viewer | Active: true | Logins: 0
User: dev_user | Role: developer | Active: false | Logins: 0

Combining Required and Default Parameters

Required parameters (no default) must come before optional ones (with default), or you must use named arguments to skip them:

// Required first, then optional
fun drawCircle(
    x: Int,
    y: Int,
    radius: Int = 10,
    color: String = "black"
) {
    println("Circle at ($x,$y) radius=$radius color=$color")
}

fun main() {
    drawCircle(50, 50)              // uses both defaults
    drawCircle(100, 200, 25)        // overrides radius
    drawCircle(0, 0, 5, "red")      // overrides both
}

Default with Expression

Default values can be expressions, not just constants:

fun logMessage(
    message: String,
    timestamp: Long = System.currentTimeMillis()
) {
    println("[$timestamp] $message")
}

fun main() {
    logMessage("App started")
    logMessage("User logged in")
}

Each call gets the current time as the default, because the expression is evaluated at call time.

Practical Example: Report Generator

fun generateReport(
    title: String,
    author: String = "System",
    pages: Int = 1,
    format: String = "PDF"
) {
    println("""
        ─────────────────────────
        Report Title : $title
        Author       : $author
        Pages        : $pages
        Format       : $format
        ─────────────────────────
    """.trimIndent())
}

fun main() {
    generateReport("Annual Sales")
    generateReport("User Guide", "Tech Team", 12)
    generateReport("Quick Note", pages = 2, format = "HTML")
}

Leave a Comment

Your email address will not be published. Required fields are marked *