Kotlinのvaragr

Kotlinのvaragr

kotlinlang.org

ドキュメントによると「Variable number of arguments」の略らしい。
function(fun)に複数の変数を渡すことが可能と記載されています。

Javaなら下記のような感じです。 testMethodの (String... strs) 部分です。

    public static void main(String args[]) {
        testMethod("a1", "b1", "c1");
    }

    private static void testMethod(String... strs) {
        Arrays.stream(strs).forEach(System.out::println); // a1 b1 c1
    }
上記をKotlinで記述すると
fun main(args: Array<String>) {
    testMethod("a1", "b1", "c1")
}

private fun testMethod(vararg strs: String) {
    Arrays.stream(strs).forEach { x: String? -> println(x) } // a1 b1 c1
}

同じ型(String)の引数をvarargを使って、渡すことができます。

KotlinのlistOfはvarargでできている
fun main(args: Array<String>) {
    val test :List<String> = listOf<String>("a1", "b1", "c1")
    println(test) // [a1, b1, c1]
}

KotlinをlistOfを使うことがよくありますが、これもlistOfの引数はvarargなんですよね。 例えば、listOfに似たFunction(fun)を作ってみます。

下記のように、listOf01のfunctionを作成してみます。vararg elementsはJavaジェネリクスですね。
Functionの引数にジェネリクスを定義したらfunの後に <T> ジェネリクスの型を定義します。
(この辺りは、Javaと同じでこういうものだと理解した方が良いでしょう)

戻り値はListを返します。Listなので、List内の方はString、Int、data classなど型指定しません。 実装内部は、mutableListOfを作成し、Listにaddしていくだけです。

fun main(args: Array<String>) {
    val test :List<String> = listOf01<String>("a1", "b1", "c1")
    println(test) // [a1, b1, c1]
}

fun <T> listOf01(vararg elements: T) :List<T> {
    val list = mutableListOf<T>()
    elements.forEach {
        list.add(it)
    }
    return list
}
スプレッド演算子 (*)

次のようなCarというdata calassのListをvaragrを使って、print01ファンクションで標準出力するにはどのようにすればよいでしょうか?

data class Car(val maker: String, val model: String, val year: Int)

fun main(args: Array<String>) {
    val list = listOf<Car>(
            Car("Toyota", "COROLLA", 1966),
            Car("Toyota", "Alphard", 2002),
            Car("Toyota", "PRIUS", 1997)
    )
    // print01ファンクションにlistを渡して標準出力する
    // print01(list)  ではコンパイルエラーとなります
}

fun print01(vararg list : Car) {
    println(list)
}

上記のような場合は、スプレッド演算子 (*) を使います。 この辺りも慣れでしょう。

data class Car(val maker: String, val model: String, val year: Int)

fun main(args: Array<String>) {
    val list = listOf<Car>(
            Car("Toyota", "COROLLA", 1966),
            Car("Toyota", "Alphard", 2002),
            Car("Toyota", "PRIUS", 1997)
    )

    print01(*list.toTypedArray())
}
fun print01(vararg list : Car) {
    println(list) // [Car(maker=Toyota, model=COROLLA, year=1966), Car(maker=Toyota, model=Alphard, year=2002), Car(maker=Toyota, model=PRIUS, year=1997)]
}

上記のようにlistをまず、toTypedArrayを使ってArray型に変換します。
次に、スプレッド演算子 (*) を使って可変長引数に変換するようにします。
(Array型を配列にする)

スプレッド演算子 (*) は次のように型の配列を渡しているのと同じようようになります。

data class Car(val maker: String, val model: String, val year: Int)

fun main(args: Array<String>) {
    print01(
            Car("Toyota", "COROLLA", 1966),
            Car("Toyota", "Alphard", 2002),
            Car("Toyota", "PRIUS", 1997)
    )
}
fun print01(vararg list : Car) {
    println(list) // [Car(maker=Toyota, model=COROLLA, year=1966), Car(maker=Toyota, model=Alphard, year=2002), Car(maker=Toyota, model=PRIUS, year=1997)]
}