2017-04-03 15 views
2

実行時にジェネリックタイプのkotlinコレクションを伝える必要があります。どうしたらいいですか?Kotlinで一般的なparamクラスを取得するには?

val list1 = listOf("my", "list") 
val list2 = listOf(1, 2, 3) 
val list3 = listOf<Double>() 

/* ... */ 

when(list.genericType()) { 
    is String -> handleString(list) 
    is Int -> handleInt(list) 
    is Double -> handleDouble(list) 
} 
+0

JVMまたはjsをターゲットにしていますか? JVM上では、kotlin refied型のほかにいくつかのリフレクションマジックがありますが、jsバックエンドでは依存することができるのはすべてrefied型です。 – glee8e

答えて

4

コトルのジェネリックスは、コンパイル時に消去されるというJavaの特徴を共有しているため、実行時に、これらのリストは、あなたが求めていることを行うために必要な情報を保持しません。例外は、修飾された型を使用してインライン関数を記述する場合です。例えば、これは動作します:

inline fun <reified T> handleList(l: List<T>) { 
    when (T::class) { 
     Int::class -> handleInt(l) 
     Double::class -> handleDouble(l) 
     String::class -> handleString(l) 
    } 
} 

fun main() { 
    handleList(mutableListOf(1,2,3)) 
} 

インライン関数は、しかし、すべての呼び出しサイトで展開され、あなたのスタックトレースを台無しので、あなたは控えめに使用する必要があります。

達成しようとしている内容にもよりますが、いくつかの選択肢があります。あなたはシールされたクラスで要素レベルで同様のことを達成できます:

sealed class ElementType { 
    class DoubleElement(val x: Double) : ElementType() 
    class StringElement(val s: String) : ElementType() 
    class IntElement(val i: Int) : ElementType() 
} 

fun handleList(l: List<ElementType>) { 
    l.forEach { 
     when (it) { 
      is ElementType.DoubleElement -> handleDouble(it.x) 
      is ElementType.StringElement -> handleString(it.s) 
      is ElementType.IntElement -> handleInt(it.i) 
     } 
    } 
} 
5

あなたはそれを行うためにinline functions with reified type parametersを使用することができます。

inline fun <reified T : Any> classOfList(list: List<T>) = T::class 

(runnable demo, including how to check the type in a when statement)

このソリューションは、Tの実際の型引数がコンパイル時に知られている場合に限られている、なぜならinline関数はコンパイル時に変換され、コンパイラは、reified型のパラメータを実際の型に置き換えますchコールサイト。

JVM上で

、ジェネリッククラスの型引数は、実行時に消去され、任意のList<T>からそれらを取得する方法は基本的にありません(たとえば、List<T>として非インライン関数に渡されたリスト - Tが知られていません

関数内のreified型パラメータをさらに制御する必要がある場合は、this Q&Aが便利です。

+0

実行可能なデモが見つかりません ":" on "のいずれかがT"になりました。 – mfulton26

+1

@ mfulton26、ありがとう、それを修正しました。 – hotkey

関連する問題