如何在Kotlin中创建具有可为空值的通用数组

问题描述 投票:0回答:2

好的,为了尝试学习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 >(private var heap:Array ,private var size:Int){我有一些...

arrays generics kotlin
2个回答
0
投票

请使用Array<T?>,而不是Array<T>

例如在类签名中,属性应为:

class Heap <T : Comparable<T>>(private var heap: Array<T?>, private var size: Int) {

如果您需要使用不为空值的输入,请使用类似以下的内容:


0
投票

数组在泛型类中很难处理,因为它们具有类型化的类型。

我认为您需要将后备数组属性移出构造函数,以使构造函数不会对可空性产生歧义。否则,类型推断将不适用于构造函数,并且即使您希望堆具有不可为null的类型,您也将不得不使用可为null的数组作为构造函数参数。无论如何,最好从构造函数中复制数组,而不是直接将其用作后备数组,因为否则,某些外部对象仍有可能仍在修改该后备数组。

由于数组始终具有类型化的类型,我认为您还需要使用类型为Any?的支持数组。这意味着您必须在公共函数中强制转换从堆中传递出去的对象。您可以为此创建一个单独的get函数,并在this[]内部使用它,以避免必须在整个类中进行强制转换。只要您不在T下方的数组部分中放置size以外的任何内容,并且您不尝试获取size以上的值,因为它们始终为空,则未经检查的强制转换是安全的并且T可能不能为空。

© www.soinside.com 2019 - 2024. All rights reserved.