在Kotlin中创建通用的二维数组

假设我有一个泛型类,我需要一个泛型类型T的二维数组。 如果我尝试以下

 class Matrix<T>(width: Int, height: Int) { val data: Array<Array<T>> = Array(width, arrayOfNulls<T>(height)) } 

编译器会抛出一个错误,说“ 不能使用'T'作为实体类型参数,而是使用一个类。

只是因为语法有所改变,下面是我的看法:

 class Array2D<T> (val xSize: Int, val ySize: Int, val array: Array<Array<T>>) { companion object { inline operator fun <reified T> invoke() = Array2D(0, 0, Array(0, { emptyArray<T>() })) inline operator fun <reified T> invoke(xWidth: Int, yWidth: Int) = Array2D(xWidth, yWidth, Array(xWidth, { arrayOfNulls<T>(yWidth) })) inline operator fun <reified T> invoke(xWidth: Int, yWidth: Int, operator: (Int, Int) -> (T)): Array2D<T> { val array = Array(xWidth, { val x = it Array(yWidth, {operator(x, it)})}) return Array2D(xWidth, yWidth, array) } } operator fun get(x: Int, y: Int): T { return array[x][y] } operator fun set(x: Int, y: Int, t: T) { array[x][y] = t } inline fun forEach(operation: (T) -> Unit) { array.forEach { it.forEach { operation.invoke(it) } } } inline fun forEachIndexed(operation: (x: Int, y: Int, T) -> Unit) { array.forEachIndexed { x, p -> p.forEachIndexed { y, t -> operation.invoke(x, y, t) } } } } 

这也允许你以类似于1d数组的方式创建2d数组,例如类似的东西

 val array2D = Array2D<String>(5, 5) { x, y -> "$x $y" } 

并使用索引操作符访问/设置内容:

 val xy = array2D[1, 2] 

问题是用非arrayOfNulls<T>(height)类型参数T调用arrayOfNulls<T>(height) 。但是我们也不能使T ,编译器会抛出下面的错误:“ 只有内联函数的类型参数可以被指定

所以这就是我们要做的。 我们使用内联工厂方法代替构造函数:

 class Matrix<T> private(width: Int, height: Int, arrayFactory: (Int) -> Array<T>) { class object { inline fun <reified T>invoke(width: Int, height: Int) = Matrix(width, height, { size -> arrayOfNulls<T>(size) }) } val data: Array<Array<T>> = Array(width, { size -> arrayFactory(size) }) } 

注意,构造函数现在是私有的,所以调用Matrix()将正确调用新的invoke()方法( 相关问题 )。 由于该方法是内联的,我们可以使用可以调用arrayOfNulls<T> 泛型 。