对象引用更改原始对象

时间:2018-02-22 06:16:33

标签: kotlin

class Adult: Resident {
    constructor(name: String, id:String): super(name, id)
    var email: String? = null
    var address: MutableList<String>? = null

    fun setAddress(s: String){
        address = s.split("\\n".toRegex()).toMutableList()
    }

}

并且这个测试用例失败了,因为

b.address = a.addressb.address?.add("Universe")也被添加到对象a

fun test6() {
    val a = Adult("Roger Widdoff","604119274")
    val b = Adult("Kathleen Craig","647022192")
    a.setAddress("123 Main Street\nAnytown, Country")
    assertEquals(2,a.address?.size)

    b.address = a.address

    b.address?.add("Universe")

    assertEquals(3,b.address?.size)

    assertEquals(2,a.address?.size)
}

我真的很困惑为什么会这样,我已经搜索了几个小时的文档。任何人都可以将我链接到某个地方来解决这个问题谢谢。

2 个答案:

答案 0 :(得分:4)

使用int main() { char* fileName; int average; getFilename(fileName); readFile(fileName); displayAverage(average); return 0; } ,您将创建一个指向现有对象实例的变量(将其视为指向存储它的内存的指针)。它没有创建副本。因此,您有两个变量b.address = a.addressb.address指向同一个对象,即a.address的实例。无论您使用哪个变量,都会对这个实例进行任何更改。

这不是Kotlin的“特色”,它是一个概括的概念,被描述为Aliasing

  

在计算中,别名描述了一种情况,即可以通过程序中的不同符号名称访问内存中的数据位置。因此,通过一个名称修改数据会隐式修改与所有别名相关联的值,这可能是程序员不期望的。

通常情况下,我建议您将列表类型更改为只读MutableList<String>,这样可以避免这个错误的测试用例。由于您无法修改测试用例,因此可以使用创建列表副本的自定义getter来解决问题:

List

答案 1 :(得分:0)

如果您想在b.address = a.address上“复制”,则应避免使用mutableList。而是使用immutable一个:

class Adult {
    constructor(name: String, id: String)

    var email: String? = null
    var address: List<String> = emptyList()

    fun setAddress(s: String) {
        address = s.split("\\n".toRegex()).toMutableList()
    }
}


class AdultTest {
    @Test
    fun test6() {
        val a = Adult("Roger Widdoff","604119274")
        val b = Adult("Kathleen Craig","647022192")
        a.setAddress("123 Main Street\nAnytown, Country")
        assertEquals(2,a.address.size)

        b.address = a.address

        b.address += "Universe"

        assertEquals(3,b.address.size)
        assertEquals(2,a.address.size)
    }
}

这里有address作为不可变列表。首先用b.address = a.address复制它只是指向同一个列表。但b.address += "Universe"只会更改b

的列表