说我有这个:
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] }
答案 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
类负责根据您提供的get
和size
实现为所有其他列表行为提供实现。
这适用于List
,但不适用于Array
。数组不能具有自定义行为。它是只存储值的原始数据类型。 List
是一个接口,可以随意修改其基本行为。