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:在超级构造函数中所做的更改将被覆盖_Kotlin - Fatal编程技术网

Kotlin:在超级构造函数中所做的更改将被覆盖

Kotlin:在超级构造函数中所做的更改将被覆盖,kotlin,Kotlin,我很难理解Kotlin到底在做什么: 我的单元测试如下所示: @Test fun testReadCursorRequest() { val xml = fromFile() val parser: ReadCursorRequestParser = ReadCursorRequestParser(xml) assertEquals(0, parser.status) assertEquals(134, parser.contacts!!.size) } 我的解

我很难理解Kotlin到底在做什么:

我的单元测试如下所示:

@Test
fun testReadCursorRequest() {
    val xml = fromFile()
    val parser: ReadCursorRequestParser = ReadCursorRequestParser(xml)
    assertEquals(0, parser.status)
    assertEquals(134, parser.contacts!!.size)
}
我的解析器是这样的

abstract class EnvelopeParser(val xml: String) {
    abstract fun parseResponse(response: Element)

    init {
        parseResponse(xmlFromString(xml))
    }

    // non-related stuff
}

类ReadCursorRequestParser(xml:String):信封解析器(xml){ 变量联系人:List=mutableListOf() 重写响应(响应:元素){ //这里有一些分析资料,填写联系人列表 println(“大小为:${contacts.size}”) } } println说
大小是:134
,单元测试说:
java.lang.AssertionError:Expected,actual


为什么?

正如您在评论中所说,
parseResponse(…)
是从
EnveloperParser
构造函数内部调用的

然后,当您创建
ReadCursorRequestParser
的实例时发生的情况是:

  • 分配了一个对象

  • 调用
    ReadCursorRequestParser
    构造函数,它立即调用超类构造函数

  • 超级构造函数(EnveloperParser的构造函数)调用
    parseResponse(…)
    ,从而分配
    联系人(此时实际上是一个非空列表)

  • 然后超级构造函数返回,
    ReadCursorRequestParser
    的构造函数继续

  • 构造函数再次分配
    联系人
    ,现在它是一个空列表

  • 原因是每个构造函数首先调用其超级构造函数(如果有),然后才初始化属性并执行
    init
    块,超级构造函数对类中声明的状态所做的所有更改(而不是基类)都将被类自己的构造函数覆盖

    此简化示例显示了以下行为:


    最简单的解决方法是将
    联系人的声明更改为

    lateinit var contacts: List<AddressBookElementParser>
    
    lateinit var联系人:列表
    
    使用此声明,构造函数将不会重新分配
    联系人


    但是我强烈建议您避免在构造函数中调用
    open
    函数,因为如果被重写,它们可能(通常是)依赖于派生类状态,而派生类状态尚未初始化,并且它们所做的更改将被派生类构造函数覆盖。您甚至可以保留部分更改,因为它们是对超类状态执行的,而另一部分则被删除了——这肯定不是您在日常生活中希望看到的情况。

    在解析内容中,是否有一个名为
    contacts
    的局部变量?如果有,则打印其大小,而不是属性中存储的
    联系人的大小。此外,您的测试似乎没有调用
    parseResponse()
    。它在哪里(或者应该被称为)?很抱歉,如果由于我刚才从这里跳过的内容而不清楚,我想让事情尽可能简短,与上下文相关。事实上,EnvelopeParser正在从其构造函数调用parseResponse。事实上,我在带有断点的调试模式下运行它,所以我100%确定没有局部变量contacts,IntelliJ在println中断时呈现contacts成员的值。
    contacts
    是不可变的。你为什么要写
    联系人?如果联系人是不可变的,Kotlin的开发人员应该重命名mutableListOf()
    
    lateinit var contacts: List<AddressBookElementParser>