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

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

问题描述

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


不能使用T作为实体类型参数。使用class而不是



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

操作符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
}
}

解决方案



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

  class Matrix2d< T>(val rows:Int,val cols:Int,private val data:Array< T>){

companion object {
operator inline fun< reified T> ; invoke(行: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。大小)抛出IllegalArgumentException(非法数组大小:$ {data.size})
}

操作符fun get(row:Int,col:Int):T = data [row * (行:Int,col:Int,v:T){
data [row * cols + col] = v
}


解决方案

Komlin数组映射到,要求在编译时知道元素类型以创建数组的实例。



所以你可以实例化 Array< String> 数组<任何> ,但不是数组< T> 其中 T 是一个类型参数,表示在编译时和henc被擦除的类型e是未知的。
为了指定在编译时必须知道类型参数,它被标记为 reified 修饰符。



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


  1. 使用 MutableList< T> 用于存储不需要通用化的元素T:

      // MutableList函数, 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(ini​​t(r,i%cols))
    }
    }

    内联趣味< reated T> Matrix2d(val rows:Int,val cols:Int,init:(Int,Int) - > T)= 
    Matrix2d(rows,cols,Array(rows * cols,{....})

    class Matrix2d< T>
    @PublishedApi内部构造函数(
    val行:Int,val cols:Int,
    private val data:Array< T>


  2. 使用数组< Any?> 作为存储,并将它的值在 get 函数中转换为 T

      val data = Array< Any?>(rows * cols,{....})

    operator fun get行:Int,col:Int):T = data [row * cols + col] as T


  3. 传入类型为 Class KClass< T> 的参数给构造函数,并使用java reflection创建一个数组的实例。



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

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

Solution

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

解决方案

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.

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

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

  3. 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
    

  4. 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天全站免登陆