Creating an instance of an array in Kotlin

Why is this not compiling? I get a compilation error in line 3

You cannot use the T parameter as a reified type. Use a class instead

class Matrix2d<T>(val rows: Int, val cols: Int, init: (Int, Int) -> T) { var data = Array(rows * cols, { i -> val r = Math.floor(i.toDouble() / cols).toInt() init(r, i - r * cols) }) operator fun get(row: Int, col: Int): T = data[row * cols + col] operator fun set(row: Int, col: Int, v: T) = { data[row * cols + col] = v } } 

Decision

I added a factory function that looks like a second constructor, but implemented in an inline function

 class Matrix2d<T>(val rows: Int, val cols: Int, private val data: Array<T>) { companion object { operator inline fun <reified T> invoke(rows: Int, cols: Int, init: (Int, Int) -> T): Matrix2d<T> { return Matrix2d(rows, cols, Array(rows * cols, { i -> val r = Math.floor(i.toDouble() / cols).toInt() init(r, i - r * cols) })) } } init { if (rows * cols != data.size) throw IllegalArgumentException("Illegal array size: ${data.size}") } operator fun get(row: Int, col: Int): T = data[row * cols + col] operator fun set(row: Int, col: Int, v: T) { data[row * cols + col] = v } } 
+4
generics kotlin
source share
1 answer

JVM arrays to which Kotlin arrays are mapped require that the element type be known at compile time in order to instantiate the array.

Thus, you can create instances of Array<String> or Array<Any> , but not Array<T> , where T is a type parameter representing the type that is erased at compile time and therefore unknown. To indicate that the type parameter should be known at compile time, it is marked with the reified modifier.

There are several options that you can do in this situation:

  • Use MutableList<T> to store items that do not require reified T:

     // MutableList function, available in Kotlin 1.1 val data = MutableList(rows * cols, { i -> val r = i / cols init(r, i % cols) }) // or in Kotlin 1.0 val data = mutableListOf<T>().apply { repeat(rows * cols) { i -> val r = i / cols add(init(r, i % cols)) } } 
  • Create an array from an inline function with a parameter of type reified:

     inline fun <reified T> Matrix2d(val rows: Int, val cols: Int, init: (Int, Int) -> T) = Matrix2d(rows, cols, Array(rows * cols, { .... }) class Matrix2d<T> @PublishedApi internal constructor( val rows: Int, val cols: Int, private val data: Array<T> ) 
  • Use Array<Any?> As storage and pass its values ​​to T in get :

     val data = Array<Any?>(rows * cols, { .... }) operator fun get(row: Int, col: Int): T = data[row * cols + col] as T 
  • Pass a parameter of type Class<T> or KClass<T> to the constructor and use java reflection to create an instance of the array.

+3
source share

All Articles