kotlin 中的层次结构问题

问题描述 投票:0回答:1

我有一个 TextElement 类,其类级别变量为

textGravity
,正在使用默认值
Element.HorizontalGravity.DEFAULT

进行初始化

TextElement
的构造函数中,我调用父类
Element
的超级构造函数,并且在该构造函数中,
textGravity
变量获得了他的值。我知道这不是一个好的做法,但它是一个具有此类结构的继承项目,由于我无法在此处解释更复杂的参数,因此目前无法更改。

问题是,在父

textGravity
类的父
decode
方法中设置
Element
之后...设置的值正在丢失,因为由于某种我不明白的原因,被重置为默认值,因为在超级构造函数之后再次调用子 TextElement 类的这一行:

var textGravity = Element.HorizontalGravity.DEFAULT

为什么会发生这种情况?这怎么可能?我怎样才能避免这种情况?

class TextElement : Element {
    var textGravity = Element.HorizontalGravity.DEFAULT

    constructor(binaryReader: BinaryReader) : super(binaryReader) {
        decode(binaryReader)
    }
}


open class Element {
    constructor(reader: BinaryReader) {
        this.decode(reader)
    }
    private fun decode(reader: BinaryReader) {
        if (this is TextElement) {
            (this as TextElement).textGravity = Element.HorizontalGravity.MIDDLE
        }
    }
}   
android kotlin hierarchy
1个回答
0
投票

超类的构造函数将在子类中的属性初始值设定项之前被调用。这是不可避免的。例如,它允许这些属性初始值设定项在超类上可靠地调用函数。

根据您的评论,您切换到

lateinit var
并摆脱了子类自己的属性初始值设定项。这需要满足以下两件事之一:

  1. 超类always设置该属性。在你的问题中确实如此,但我认为真正的代码比这更复杂。 😀

  2. 或者,您需要使用诸如

    ::textGravity.isInitialized
    之类的东西来保护对该属性的使用,因此如果您尚未初始化它,则不要尝试使用它。例如,我认为您可以在属性声明/初始化程序之后有一个
    init
    块,它会仔细检查属性是否已初始化,如果没有初始化,则对其进行初始化。

正如您在问题中指出的那样,这段代码总体来说有点可怕,您被困住了。将来阅读这个问题的其他人(👋🏻)可能会尝试重新处理问题,以便超类不会尝试以这种方式弄乱超类构造函数中的子类属性。

© www.soinside.com 2019 - 2024. All rights reserved.