Kotlin:在超级构造函数中所做的更改将被覆盖
我很难理解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) } 我的解
@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
构造函数,它立即调用超类构造函数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>