[毎日Kotlin] Day4. Default arguments(デフォルト引数)

2018.01.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

毎日Kotlinシリーズです。

このシリーズを初めての方はこちらです。「毎日Kotlin」はじめました | Developers.IO

問題

デフォルト引数を使ってみよう。

Default arguments | Try Kotlin

There are several overloads of 'foo()' in Java:

public String foo(String name, int number, boolean toUpperCase) {
    return (toUpperCase ? name.toUpperCase() : name) + number;
}
public String foo(String name, int number) {
    return foo(name, number, false);
}
public String foo(String name, boolean toUpperCase) {
    return foo(name, 42, toUpperCase);
}
public String foo(String name) {
    return foo(name, 42);
}

All these Java overloads can be replaced with one function in Kotlin. Change the declaration of the function foo in a way that makes the code using foo compile. Use default and named arguments.

fun foo(name: String, number: Int, toUpperCase: Boolean) =
        (if (toUpperCase) name.toUpperCase() else name) + number

fun useFoo() = listOf(
        foo("a"),
        foo("b", number = 1),
        foo("c", toUpperCase = true),
        foo(name = "d", number = 2, toUpperCase = true)
)

狙い

ここで考えて欲しい問題の意図はなんだろうか?

デフォルト引数もJavaにない機能です。呼びたい引数の数だけオーバーロードをしないといけなかったのが、指定しないときのデフォルト値を設定できるようになりました。かなり便利です。

解答例

fun foo(name: String, number: Int = 42, toUpperCase: Boolean = false) =
        (if (toUpperCase) name.toUpperCase() else name) + number

引数の定義の後に = でデフォルト値をつけるだけです。たとえば、number: Int = 42なら、numberを指定しない場合は42が入るという意味です。

補足

もし新しくデフォルトの値のないtel:string(電話番号)を追加することになったときに以下の2つどちらよいでしょうか?両者ともコンパイルできます。

fun foo(name: String, tel: String, number: Int = 42, toUpperCase: Boolean = false) =
        (if (toUpperCase) name.toUpperCase() else name) + number + tel
fun foo(name: String, number: Int = 42, toUpperCase: Boolean = false, tel: String) =
        (if (toUpperCase) name.toUpperCase() else name) + number + tel

例えば、nameとtelだけ指定し、他はデフォルト値をそのまま使いたいときはどのようになるでしょう?

fun foo(name: String, tel: String, number: Int = 42, toUpperCase: Boolean = false) =
        (if (toUpperCase) name.toUpperCase() else name) + number + tel
foo("kamedon", "090-0000-0000")

定義の順番に値を入れる。

fun foo(name: String, number: Int = 42, toUpperCase: Boolean = false, tel: String) =
        (if (toUpperCase) name.toUpperCase() else name) + number + tel
        
foo("kamedon", 42, false, "090-0000-0000") 
foo("kamedon", tel = "090-0000-0000")

telがデフォルト引数の後にあるため、nameとtelを指定したいだけなのに、途中の引数をすべてデフォルト値を再度指定するか、あるいは名前付き引数でtelを指定しなければなりません。少し面倒です。

デフォルト引数を使う場合は、デフォルトなし引数を最初に寄せて、デフォルトあり引数を後ろに寄せたほうが、メソッドを使用する人はわかりやすくなります。

あとがき

Day5.でまたお会いしましょう。