好的,为了尝试学习kotlin语言,我正在尝试实现堆。
class Heap <T : Comparable<T>>(private var heap: Array<T>, private var size: Int){
我在可为空类型的行为方面遇到一些困难。一开始我给出了一系列元素,但是当我想分配更多元素时开始遇到困难]
,则会收到错误消息private fun increaseSize(){ if(size == heap.size){ //okay this is garbage var enlargedHeap = arrayOfNulls<Comparable<*>>(heap.size * 2) as Array<T> System.arraycopy(heap, 0, enlargedHeap, 0, size) heap = enlargedHeap } }
所以在这里我想我正在将堆从
Array<T>
更改为Array<T?>
,这很有意义。因此,我也更改了构造函数,取为Array<T?>
,无论我在哪里尝试访问heap[x]
,它都建议了一些非常有趣的事情。else heap[pos1].compareTo(heap[pos2]) < 0
to
else heap[pos2]?.let { heap[pos1]?.compareTo(it) }!! < 0
然后我看了一个提示,指出
arrayOfNulls<Comparable<*>>(heap.size * 2) as Array<T>
返回了Array<T>
但是,当执行
arrayOfNulls
时,它的确返回一个具有空值的数组。但是,如果尝试heap[x] = null
状态
Null不能是非null类型T的值
如果我将构造函数更改为采用
Array<T?>
,那么输入数组也必须显式可为null。我固定了哪个
class Heap <T : Comparable<T>>{ private var heap: Array<T?> private var size = 0 constructor(heap: Array<T>, size){ this.heap = heap as Array<T?> this.size = size }
但是现在当我尝试使用具有可空值的数组实例化具有空值的数组时,它不接受]
var arr = arrayOfNulls<String>(9) var heap = Heap(arr, arr.size-1)
所以现在我需要两个构造函数?发生了什么
类型不匹配。必需:可比较的找到:字符串吗?
即使Àrray<T?>
也存在错误,因为compareTo不接受可为空的值。
即使进行检查仍会给出错误
return if(pos2 > size || (heap[pos1] == null || heap[pos2] == null)) false else heap[pos1].compareTo(heap[pos2]) < 0
类型不匹配。必需:T找到的:T?
如何允许数组包含空值?
希望不会使Array<T>
为空,因为它会破坏compareTo的值,并且多个构造函数看起来像是不良设计。
[好,因此,为了尝试学习kotlin语言,我正在尝试实现堆。 class Heap
请使用Array<T?>
,而不是Array<T>
。
例如在类签名中,属性应为:
class Heap <T : Comparable<T>>(private var heap: Array<T?>, private var size: Int) {
如果您需要使用不为空值的输入,请使用类似以下的内容:
数组在泛型类中很难处理,因为它们具有类型化的类型。
我认为您需要将后备数组属性移出构造函数,以使构造函数不会对可空性产生歧义。否则,类型推断将不适用于构造函数,并且即使您希望堆具有不可为null的类型,您也将不得不使用可为null的数组作为构造函数参数。无论如何,最好从构造函数中复制数组,而不是直接将其用作后备数组,因为否则,某些外部对象仍有可能仍在修改该后备数组。
由于数组始终具有类型化的类型,我认为您还需要使用类型为Any?
的支持数组。这意味着您必须在公共函数中强制转换从堆中传递出去的对象。您可以为此创建一个单独的get函数,并在this[]
内部使用它,以避免必须在整个类中进行强制转换。只要您不在T
下方的数组部分中放置size
以外的任何内容,并且您不尝试获取size
以上的值,因为它们始终为空,则未经检查的强制转换是安全的并且T
可能不能为空。