Kotlin ジェネリック(Generic)

ジェネリッククラス

引数をAny型として受け取り、Any型のプロパティに保存することで、IntCharStringなど、さまざまな型に応じたクラスや関数を定義できる。

class Foo(val value: Any)

fun main() {
    val a1 = Foo(123)
    println(a1.value)		// 123
}

しかしvalueはAny型なので、次のようにvalue+ 1演算を行うとエラーが発生する。

class Foo(val value: Any)

fun main() {
    val a1 = Foo(123)
    println(a1.value + 1)	// Error
}

<T>でジェネリック型を定義することで、valueはIntCharStringなど、引数に応じた型のプロパティとして扱われ、この問題を解決できる。

class Foo<T>(val value: T)

fun main() {
    val a1 = Foo(123)
    println(a1.value + 1)	// 124
}

次のように型に制限をかけることができる。ここではIntDoubleなど、Numberのサブクラスに制限している。

class Foo<T: Number>(val value: T)

ジェネリック関数

関数でもジェネリックを使用できる。次は任意の型Tの引数を受け取り、T型の値を返す関数である。

fun <T> foo(x: T): T { ... }

呼び出し時に型を指定するが、引数によって型が明確な場合は省略できる。

foo<Int>(123)
foo<String>("ABC")
foo(123)
foo("ABC")

次のように型に制限をかけることができる。ここではIntDoubleなど、Numberのサブクラスに制限している。

fun <T: Number> foo(x: T): T { ... }

制約条件を複数指定するにはwhereを使用する。

fun <T> foo(x: T) where T: Runnable, T: Cancellable { ... }