Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
kotlin自定义从mutableList获取不可变列表_Kotlin - Fatal编程技术网

kotlin自定义从mutableList获取不可变列表

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

我有一个用于可变列表的自定义getter方法,可以使用Google的Guava库返回不可变列表。然后在构造函数中访问这个可变列表

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
)