kotlin自定义从mutableList获取不可变列表
我有一个用于可变列表的自定义getter方法,可以使用Google的Guava库返回不可变列表。然后在构造函数中访问这个可变列表kotlin自定义从mutableList获取不可变列表,kotlin,Kotlin,我有一个用于可变列表的自定义getter方法,可以使用Google的Guava库返回不可变列表。然后在构造函数中访问这个可变列表 data class mutableClass(val list: List<Foo>) { private val mutableList: MutableList<Foo> get() = ImmutableList.copyOf(field) init { mutableList = mu
data class mutableClass(val list: List<Foo>) {
private val mutableList: MutableList<Foo>
get() = ImmutableList.copyOf(field)
init {
mutableList = mutableListOf()
list.forEach {
mutableList.add(it.copy()) // Exception is thrown here.
// It actually calls its getter method which is an immutable
// list, so when init this class, it throw exception
}
}
}
data class Foo {}
数据类可变类(val列表:列表){
私有val可变列表:可变列表
get()=ImmutableList.copyOf(字段)
初始化{
mutableList=mutableListOf()
list.forEach{
mutableList.add(it.copy())//此处引发异常。
//它实际上调用其getter方法,该方法是不可变的
//所以当初始化这个类时,它抛出异常
}
}
}
数据类Foo{}
我将其反编译为Java,在init块中,它调用mutableList的getter方法。
有没有办法调用mutabbleList本身而不是getter方法?当然,它会调用getter(返回
ImmutableList.copyOf(field)
)
您可以在init
块中简单地分配到mutableList
新复制的可变列表:
data class MutableClass(val list: List<Foo>) {
private val mutableList: MutableList<Foo>
get() = ImmutableList.copyOf(field)
init {
mutableList = list.map { it.copy() }.toMutableList()
}
}
Kotlin stdlib选择接口不变性。这意味着,装入实现的接口决定了引用本身的可变性 因此,制作一个
可变列表
只是一个列表
的正确方法是将其框起来,如下所示:
val myMutableList = mutableListOf(1, 2, 3, 4)
val myImmutableList = myMutableList as List<Int>
。。。如果您能够通过取消装箱来访问可变实现,您可以选择以下解决方案:
class ImmutableList<T>(list: MutableList<T>) : List<T> by list
fun <T> MutableList<T>.toImmutable() = ImmutableList(this)
因此,您将避免上述问题。实际上,从MutableList.toImmutable()
返回的值取消装箱的任何尝试都会导致TypeCastException
,因为List
的实现不再是MutableList
。相反,它是一个不可变列表
,它不公开任何可能改变对象的方法
与@Lucas方法不同,这种方法不会浪费时间来复制元素,因为您将依赖Kotlin中的
by
关键字,它允许您通过现有的实现来实现接口。也就是说,MutableList
您将传递给ImmutableList
的构造函数当我研究这个主题时,它最适合我的解决方案就是通过契约强制执行。如果您要创建一个可变列表,可以这样说:
val immutableList = mutableListOf(
Randomy.One,
Randomy.Two,
Randomy.Three
).toList() // We make it immutable?
然后使用扩展函数或下面给出的任何建议,如使用ImmutableList.copyOf(field)
,您可能会因为将项目复制到另一个集合而受到惩罚
另一种选择是支付拆箱成本,例如:
val myImmutableList = myMutableList as List<Int>
现在,如果我们与另一个组件共享该列表,我们将使用正确的抽象,而不会产生任何成本。我们也可以使用集合,因为列表继承自集合:
val immutableList: Collection<Randomy> = mutableListOf(
Randomy.One,
Randomy.Two,
Randomy.Three
)
val immutableList:Collection=mutableListOf(
随机的,一个,
随机的,两个,
随机的,三个
)
对我来说,使用var而不是val字段以及私有setter通常效果最好
类顺序
类某物(){
变量顺序:List=listOf()
专用设备
订单(订单:订单){
订单=订单
.toMutableList()
.apply{add(order)}
}
}
这会将其公开为不可变的,并且只需要一个字段。我们付出的代价是在添加元素时创建新集合的开销。这是完整的代码吗?由于该属性是私有的,所以没有不可变的列表是没有意义的,它根本不可访问。您还必须考虑到您拥有的属性“代码>清单< /代码>,因此使用工厂实现类可能是值得的。
val immutableList = mutableListOf(
Randomy.One,
Randomy.Two,
Randomy.Three
).toList() // We make it immutable?
val myImmutableList = myMutableList as List<Int>
val immutableList: List<Randomy> = mutableListOf(
Randomy.One,
Randomy.Two,
Randomy.Three
)
val immutableList: Collection<Randomy> = mutableListOf(
Randomy.One,
Randomy.Two,
Randomy.Three
)