我正在尝试在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 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) {
...
}
当两者具有相同的构造函数时,不确定为什么Kotlin将MyArray与常规数据区别对待?
答案 0 :(得分:5)
创建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)
答案 1 :(得分:0)
根据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))
}
}
这允许通过使用伴随对象将reified用作构造函数。可以使用operator invoke完成构造调用约定。这现在有效:
fun main(args: Array<String>){
val m = NDArray(4,4, ::zero)
}
fun zero(i:Int) = 0.0
唯一的问题(复杂的语法invoke()除外)是NDArray构造函数需要是公共的。还有更好的方法吗?
请注意!以下问题KT-11182会影响此设计模式