Kotlin带有自定义吸气剂的属性数组

时间:2019-02-01 10:02:51

标签: kotlin

说我有这个:

class NumWithSuccessor {
    var num = 1
    val successor
        get() = num + 1
}

现在,如果我想要一个num的数组,

class NumsWithSuccessors {
    var nums = Array<Int>(3){ 1 }
    val successor
        get() = /* What? */
}

我的第一个猜测是使用

get() = { Array<Int>(3){ nums[it] + 1 } }

但是,这将导致每次我需要访问后继者时都会创建一个新数组。 有一种简单,更好的方法吗?

实际示例:

// Need to go from this...
private val _dayWiseEventsList =             // For internal use
        MediatorLiveData<List<Event>>()

val dayWiseEventsList: LiveData<List<Event>> // For immutable, external observation
        get() = _dayWiseEventsList


// ... to this
private val _dayWiseEventsListArray =        // For internal use
        Array<MediatorLiveData<List<Event>>>(DAYS) { MediatorLiveData() }

val dayWiseEventsListArray                   // For immutable, external observation
        // Need an alternative for this
        get() = Array<LiveData<List<Event>>>(DAYS) { _dayWiseEventsListArray[it] }

4 个答案:

答案 0 :(得分:1)

您可以延迟初始化它:

val successor by lazy { Array<Int>(3){ nums[it] + 1 } } 

这只会在第一次访问数组时创建一次数组,然后在后续访问时将返回相同的数组。

但是请注意,如果您修改successor,这将不会更新nums。如果要更新它,则需要为nums设置一个客户设置器,并相应地更新successor


就像我在评论中解释的那样,我将使所有这些变得不可变,例如:

data class NumsWithSuccessors(val nums: List<Int> = List(3){ 1 }) {
    val successor by lazy { nums.map { it + 1 } }
}

答案 1 :(得分:0)

successor不能依赖nums,具有val修饰符,并且不能同时使用缓存的数组。解决方案是每次访问map属性时都使用successor函数创建一个新列表:

class NumWithSuccessor {
    var nums = Array<Int>(3){ 1 }
    val successor
        get() = nums.map { it + 1 }
}

答案 2 :(得分:0)

您可以为num创建一个setter,并使用map运算符在其中设置后继值。这样可以防止每次创建新数组:

class NumsWithSuccessors {
    var successor: Array<Int> = arrayOf()
    var nums: Array<Int> = Array(3) { 1 }
    set(value) {
        field = value; successor = value.map { it + 1 }.toTypedArray()
    }

答案 3 :(得分:0)

class NumsWithSuccessors {
    var nums: List<Int> = List(3){ 1 }
    val successors: List<Int> = object: AbstractList<Int>() {
        override val size get() = nums.size
        override fun get(index: Int) = nums[index] + 1;
    }
}

在上面的示例中,successors是虚拟的List,实际上并不包含数据。当您尝试从successors中读取项目时,它仅查看基础nums列表以计算值。 AbstractList类负责根据您提供的getsize实现为所有其他列表行为提供实现。

这适用于List,但不适用于Array。数组不能具有自定义行为。它是只存储值的原始数据类型。 List是一个接口,可以随意修改其基本行为。