Kotlin NDArray与一个带有泛型返回类型的lambda构造函数

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

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

典型的用法是:

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

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

 values = Array(i * j, f) 

通过说“不能使用'T'作为通用类型参数。 为什么?

编辑:

如果我用我自己的MyArray替换Kotlin数组实现,它会编译:

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

不知道为什么Kotlin将MyArray与正则数组区别对待,当两者具有相同的构造函数时?

创建一个Java数组需要指定一个元素类型。 在您的类中,元素类型仅作为类的类型参数提供,而Java中的泛型在运行时会被删除。 因此,数组的元素类型是未知的,并且不可能创建它。

如果你想创建一个标准的Array<T>的自定义包装,它将不得不如下所示:

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

reified关键字意味着你的T没有被擦除,并且可以用在需要真实类的地方,比如调用Array()构造函数。

请注意,此类语法不支持类构造函数,但对于工厂函数仍然有用(必须inline d)

 fun <reified T> arrayFactory(i:Int, j:Int, init: (Int) -> T) = Array<T>(i * j, init) 

基于yole和voddan的输入,这是迄今为止我发现的最好的解决方案:

 class NDArray<T>(val values: Array<T> ){ companion object Factory{ inline operator fun <reified T>invoke(i: Int, j: Int, noinline init: (Int) -> T) = NDArray(Array(i * j,init)) } } 

这允许通过使用伴随对象来使用具体化作为构造函数。 构造调用约定可以使用操作符调用完成。 现在这个工作:

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

唯一的问题(除了复杂的语法invoke())是NDArray构造函数需要公开。 也许还有更好的方法吗?

注意! 以下问题KT-11182影响这种设计模式