Passing null value to Kotlin method with non nullable default arguments

Viewed 1070

I am new to Kotlin and I found one of the features which Kotlin differs from Java is method default arguments. https://kotlinlang.org/docs/functions.html#default-arguments

I am creating a simple Kotlin application which passes null values to a method with 2 non nullable default arguments, which results in a compilation error - Type mismatch: inferred type is String? but String was expected).

fun greet(firstName: String = "Hello", lastName: String = "world") {
    println("${firstName} ${lastName}")
}

fun main(args: Array<String>) {
    greet(args.getOrElse(0) { null }, args.getOrElse(1) { null })
}

One workaround is to change the method arguments to nullable, but the cleaniness of the original method is lost.

fun greet(firstName: String?, lastName: String?) {
    val firstName2 = firstName ?: "Hello"
    val lastName2 = lastName ?: "world"
    println("${firstName2} ${lastName2}")
}

fun main(args: Array<String>) {
    greet(args.getOrElse(0) { null }, args.getOrElse(1) { null })
}

If I have to keep the original method signature, I can think of below alternative solutions.

Duplicate the default argument definitions in method signature and method caller

fun greet(firstName: String = "Hello", lastName: String = "world") {
    println("${firstName} ${lastName}")
}

fun main(args: Array<String>) {
    greet(args.getOrElse(0) { "Hello" }, args.getOrElse(1) { "world" })
}

Separate method calls based on the number of arguments

fun greet(firstName: String = "Hello", lastName: String = "world") {
    println("${firstName} ${lastName}")
}

fun main(args: Array<String>) {
    when (args.size) {
        0 -> greet()
        1 -> greet(args[0])
        2 -> greet(args[0], args[1])
    }
}

All 3 solutions print Hello world when no argument is supplied. I am wondering if there are other better alternative solutions.

1 Answers

Rather than using default arguments, it's better to be explicit and validate your inputs, then you can avoid the ambiguity:

fun greet(firstName: String, lastName: String) = println("$firstName $lastName")

fun main(args: Array<String>) {
    require(args.size == 2) { "Must supply two arguments" }
    val (arg1, arg2) = args
    greet(arg1, arg2)
}
Related