在Kotlin中实例化泛型数组 [英] Instantiating generic array in 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
修饰符。
有几种选择,您可以在这种情况下做什么:
-
使用
MutableList< T>
用于存储不需要通用化的元素T:// MutableList函数, Kotlin 1.1
$ p
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))
}
}
内联趣味< 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>
)
-
使用
数组< Any?>
作为存储,并将它的值在get
函数中转换为T
:val data = Array< Any?>(rows * cols,{....})
operator fun get行:Int,col:Int):T = data [row * cols + col] as T
-
传入类型为
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:
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> )
Use
Array<Any?>
as the storage, and cast its values toT
inget
function: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>
orKClass<T>
to constructor and use java reflection to create an instance of array.
这篇关于在Kotlin中实例化泛型数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!