在 Kotlin 中实例化泛型数组 [英] Instantiating generic array in Kotlin

查看:34
本文介绍了在 Kotlin 中实例化泛型数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这不能编译?我在 3 行中遇到编译错误

Why this doesn't compile? I get compile error in 3 line

不能使用 T 作为具体化的类型参数.改用类

Cannot use T as reified type parameter. Use 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
   }
}

解决方案

我添加了一个工厂函数,它看起来像第二个构造函数,但在内联函数中实现

I added a factory function which looks like a second constructor but implemented in 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
   }
}

推荐答案

Kotlin 数组映射到的 JVM 数组,需要在编译时知道元素类型才能创建数组实例.

JVM arrays, on which Kotlin arrays are mapped to, require the element type to be known at compile time to create an instance of array.

所以你可以实例化ArrayArray,但不能实例化Array,其中T 是一个类型参数,表示在编译时擦除的类型,因此是未知的.为了指定一个类型参数在编译时必须是已知的,它被标记为 reified 修饰符.

So you can instantiate 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 hence is unknown. To specify that a type parameter must be known at compile time it is marked with reified modifier.

有几种选择,在这种情况下你可以做什么:

There are several options, what you can do in this situation:

  1. 使用MutableList来存储元素,不需要具体化的T:

  1. Use MutableList<T> for storing elements, which doesn't 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 reified type parameter:

    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>
        ) 
    

  • 使用Array作为存储,并在get函数中将其值转换为T:>

  • Use Array<Any?> as the storage, and cast its values to T in get function:

    val data = Array<Any?>(rows * cols, { .... })
    
    operator fun get(row: Int, col: Int): T = data[row * cols + col] as T
    

  • ClassKClass 类型的参数传递给构造函数,并使用 java 反射来创建数组的实例.

  • Pass a parameter of type Class<T> or KClass<T> to constructor and use java reflection to create an instance of array.

    这篇关于在 Kotlin 中实例化泛型数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆