Kotlin NDArray具有带通用返回类型的lambda构造函数

Tom*_*son 5 arrays generics type-erasure kotlin

我正在尝试在Kotlin中创建一个非常简单的通用NDArray类,该类将lambda表达式用作初始化函数。

class NDArray<T>(i: Int, j: Int, f: (Int) -> T) {
    val values: Array<T> =  Array(i * j, f)
}
Run Code Online (Sandbox Code Playgroud)

典型的用法是:

fun main(args: Array<String>){
    val m = NDArray(4, 4, ::zero)
}

fun zero(i: Int) =  0.0
Run Code Online (Sandbox Code Playgroud)

我的问题是Kotlin编译器抱怨构造函数中的值初始化

values = Array(i * j, f)
Run Code Online (Sandbox Code Playgroud)

通过说“不能使用'T'作为化类型参数。改为使用类”。为什么呢

编辑:

如果我改为用自己的MyArray代替Kotlin Array实现,则会编译:

class NDArray<T>(i: Int, j: Int, f: (Int) -> T) {
    val values: MyArray<T> =  MyArray(i * j, f)
}

class MyArray<T>(i:Int, init: (Int) -> T) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

不确定当Kotlin具有相同的构造函数时,为什么Kotlin将MyArray与常规Array区别对待吗?

yol*_*ole 5

创建Java数组需要指定元素类型。对于您的类,元素类型仅作为类的类型参数提供,并且Java泛型在运行时被擦除。因此,数组的元素类型未知,因此无法创建它。

如果要围绕standard创建自定义包装器Array<T>,则必须如下所示:

class NDArray<reified T>(i:Int, j:Int, init: (Int) -> T) {
    val arr = Array<T>(i * j, init)
}
Run Code Online (Sandbox Code Playgroud)

reified关键字意味着你T不会被擦除,并可以在需要一个真正的类一样调用地方使用Array()构造函数。

请注意,类构造函数不支持语法,但对于工厂功能仍然有用(必须为inlined)

fun <reified T> arrayFactory(i:Int, j:Int, init: (Int) -> T) = Array<T>(i * j, init)
Run Code Online (Sandbox Code Playgroud)