ここでは、Kotlin における型パラメータ、ジェネリクスについてまとめています。
ジェネリクス:どんな時に使う?
例えば以下のように、リストやセットのようなオブジェクトのコンテナとなるクラスを宣言したとします。
参考
リストやセットについては、「Collection(コレクション)」にまとめています。
|
1 2 |
class Container(var value: Any) |
クラス Container の引数の型は Any を指定しており、任意の型のオブジェクトを格納できるクラスで、
以下のように使います。
|
1 2 3 4 5 6 7 8 9 10 |
fun main() { val intContainer = Container(123) val number = intContainer.value as Int println(number) // 123 val strContainer = Container("Kotlin") val string = strContainer.value as String println(string) // Kotlin } |
Any 型を指定することで、プロパティ value の型は Int や String として使うことができます。
しかし、これは危険かつ面倒なことになります。
誤って型変換すると危険
例えば、「Container(123).value as String」とすると、ClassCastException の例外が発生します。
オブジェクトの型が Int であるにもかかわらず、String にキャストしようとしたからです。
様々な型にクラスを用意
キャストができないのであれば、BooleanContainer や LongContainer など、
様々な型に対応するクラスを作れば回避できます。
しかしこれは、面倒ですね。
独自で定義したクラスに対応していくと、きりがありません。
そこで登場するのが、「ジェネリクス」という仕組みです。
クラスは、「型パラメータ」を取ることができます。
ジェネリクス:使い方
どのようにクラスを定義するのか、先ほどの例をもとに以下のように記述します。
|
1 2 |
class Container<T>(var value: T) |
クラス名の直後に <T> と記述して型パラメータを受け取るようにします。
Tは、別の名前でも構いませんが、他言語を含めて T を使うのが一般的です。
ジェネリクスのクラスは、以下のように使用します。
|
1 2 3 4 5 6 7 8 9 10 |
fun main() { val intContainer: Container<Int> = Container<Int>(123) val number: Int = intContainer.value println(number) // 123 val strContainer = Container("Kotlin") val string = strContainer.value println(string) // Kotlin } |
例のように、Int や String などの型引数 を与えます。
String 型の使用例のように、型推論ができる場合に関しては省略することも可能です。