ProgrammingKotlin開発者

Kotlinにおける'vararg'はどのように機能しますか?引数の渡し方、制限、一般的なパターンとの相互作用、名前付き引数と通常の引数の組み合わせ時の典型的な難しさについて説明してください。

Hintsage AIアシスタントで面接を突破

回答。

Kotlinにおける'vararg'キーワードは、関数が可変数の引数を受け取ることを可能にします。これはJavaの配列と同等ですが、追加の構文的な糖衣があります。

ルールと制限:

  • 通常の構文: fun foo(vararg numbers: Int)
  • vararg引数は関数のパラメータの中で最後でなければなりません(その後にパラメータがある場合、それらは呼び出すときに名前付きである必要があります)。
  • 別々の値としても、配列を使って(スプレッドオペレーター*を使用)渡すことができます。
  • varargを持つ関数は、その引数の値を渡さずに呼び出すことができます。

コード例

fun printAll(vararg strings: String) { for (s in strings) println(s) } val arr = arrayOf("a", "b", "c") printAll("one", "two") // 正常に動作する printAll(*arr) // スプレッド(配列を展開)

トリックの質問。

一つの関数に二つの'vararg'パラメータを宣言したり、'vararg'を最後でない位置に置いたりすることはできますか?

回答: いいえ、Kotlinでは関数の宣言に一つのvarargしか使用できず、常に位置引数の最後でなければなりません。それの後に通常のパラメータを追加すると、それは名前でのみ渡すことができます。

例:

fun foo(vararg items: String, prefix: String) // コンパイルエラー! // 正しい: fun foo(vararg items: String, vararg items2: Int) // コンパイルエラー! // 動作する: fun foo(vararg items: String, prefix: String = "[default]") foo("a", "b", prefix = "->")

このテーマの微妙な知識不足による実際のエラーの例。


物語

若いプログラマーは即座に二つのvarargパラメータを同時に宣言できると思い込んでいました。関数のアーキテクチャは、呼び出しのいくつかのレベルで分割されていたため、これは一連のリファクタリングにつながり、受け入れたデータのロジックを見直し、すべての呼び出しを書き直す必要がありました。


物語

Androidプロジェクトでは、varargパラメータを持つ関数に配列を渡す際にスプレッドオペレーター*を使用するのを忘れました:printAll(arr)の代わりにprintAll(*arr)。その結果、配列の要素がオブジェクトのアドレスとして一つの文字列として出力され、論理的にアプリケーションは奇妙に行動しました。


物語

varargと追加の名前付きパラメータを持つ関数fun foo(vararg a: Int, b: Int)では、位置引数での呼び出しが正しく解釈されませんでした。コンパイラはvarargのリストがどこで終了し、引数bが始まるのかを判断できず、コンパイル時エラーを引き起こしました。こうしたパラメータに対しては、引数名を明示的に使用することに決めました。