[Kotlin]4種類のアンダースコアが持つ意味

「_」←下に横棒、これ何て読んでます?

アンダースコア、アンダーバー、下線、ちょっとマイナーどころだとアンダーライン、ローラインなんて読み方もあるそうです。

このサイトではアンダースコアと呼びますが、このアンダースコア、Kotlinの予約語の1つでもあります。

今回はどこで使われるかによって微妙に意味が異なる「アンダースコア」について。

(ちなみに動画投稿で生きている永遠の17歳はアンダーバーです)


動画投稿で生きる! フリーダムな仕事術 __(アンダーバー)自伝

コンストラクタ引数のアンダースコア

最初に「クラスのコンストラクタ引数」に使われるアンダースコア。

class Player(val name: String, _age: Int){
    var age: Int = _age

    fun squareAge(): Int = age * age
    fun multiplyAge(n: Int): Int = age * n
}

2つ目のパラメータである_ageに注目してみましょう。名前がアンダースコアから始まっています。

はっきり言ってしまうと、このアンダースコア自体には特別な意味はありません。しかし無い場合と比べてみてください。

class Player(val name: String, age: Int){
    var age: Int = age

    fun square(): Int = age * age
    fun multiply(n: Int): Int = age * n
}

どちらの方が引数とプロパティとを判別しやすいでしょうか?

引数の「age」とプロパティの「age」は型が違う別の値です。こんな風に名前が被ってしまうと、どちらがどちらの「age」なのか判別し難いという事態に陥ります。

このクラスにはageプロパティの値を使用するメソッドを2つ定義しています。しかし「_age」は引数とプロパティの初期化にしか使われていません。このように一時的にしか使われない変数はアンダースコアを頭に付けることで、

  • 引数に取った値そのままであることが明確になる
  • 引数とプロパティを明確に区別できる

といった利点があります。使用するかどうかはあくまで自由ですが、あった方が可読性が上がるのであれば適時使用しましょう。

数値のアンダースコア

こちらは簡単。桁が多い数値には、可読性向上のために任意の数のアンダースコアを付けることができます。

println(1_000_000_000)
//1000000000

ラムダ式のアンダースコア

上記2つとは別に、ラムダ式の引数にアンダースコアを使用する場合があります。

val example = mapOf(1 to "Kotlin", 2 to "Java")
example.forEach{(_, v)-> println(v)}
//Kotlin
//Java

forEachはMap型から呼び出してラムダ式の引数を2つ設定すると、その要素であるPair型のキー/バリューをそれぞれ参照しますが、この例では第一引数をアンダースコアで表記しています。

このアンダースコアは「この引数は今後使用しない」という宣言です。

アンダースコアで表記された引数は、そのラムダ式内では使用できません。

example.forEach{(_, v)-> println(_)}
//エラー :Unresolved reference: _
//エラー :Names _, __, ___, ..., are reserved in Kotlin

文法的には問題無いようにも思えますが、アンダースコアはKotlinの予約語の1つ。「未使用」の宣言以外でのアンダースコアの使用はエラーになります。

分解宣言のアンダースコア

最後に分解宣言で利用されるアンダースコアです。

val (x, y, z) = Triple(1, 2, 3)

これは通常の分解宣言。左辺と右辺の値が同数であれば、右辺の値を複数の変数に一気に代入することができます。

val (_, y, z) = Triple(1, 2, 3)

左辺最初の変数をアンダースコアにした形。意味的にはラムダ式のときと同じ、「この部分は変数として利用しない」という宣言です。

この場合、変数yとzにはそれぞれ2と3が入ります。

val (x, _, z) = Triple(1, 2, 3)

2番目の値を使用しないならこの形。1と3が変数に代入されます。

val (x, y, _) = Triple(1, 2, 3)
val (x, y) = Triple(1, 2, 3)

最後の値を代入しない場合は記述自体を省略可能。上の2つは等価です。

参考文献

Kotlinのキーワード(予約語)と演算子一覧。

https://kotlinlang.org/docs/reference/keyword-reference.html

PairとTripleのAPIリファレンス。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-triple/

タイトルとURLをコピーしました