没有初始化块的子类中的参数为空,尽管参数为非空

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

我有两个类控制 Android 中的按钮。

SortingButton 类用于一个简单的 Button,您可以使用它选择升序/降序排序

    open class SortingButton(
    protected val context: Context?,
    private val binding: FragmentDualSortingBinding,
    private var orderState: SortingOrderEnum,
    protected val button1: MaterialButton,
    protected val button2: MaterialButton) {
    // this class cares for the two buttons on the left
    // only for the importance

    init {
        this.onCreate()
  
    }

    open fun onCreate() {
         ...
        }

带有两个按钮的复杂排序按钮。一种用于排序类型,一种用于升序/降序

    class ComplexSortingButton(
    context: Context?,
    binding: FragmentDualSortingBinding,
    orderState: SortingOrderEnum,
    private var evaluator : SecondaryEvaluator?,
    button1: MaterialButton,
    button2: MaterialButton
    ) : SortingButton(context, binding, orderState, button1, button2) {

    init {
        onCreate()
    }

    override fun onCreate() {
        Log.d("ComplexSortingButton", "onCreate - evaluator: $evaluator")
        super.onCreate()
        
    }

现在,当我将非空参数

evaluator
传递给 ComplexSortingButton 时,我收到
evaluator
作为
null

我有一个解决方案。但我不知道为什么它会起作用。

将 init-block 放入 ComplexSortingButton 时,收到时

evaluator
不再为 null。

init {
    this.onCreate()
}

为什么?

android kotlin init
1个回答
0
投票

你永远不应该从类的构造函数中调用 open 函数,因为它可能会导致不一致/意外的状态、空指针异常等。我很惊讶 Kotlin 甚至允许你在没有编译错误的情况下执行此操作,但它至少可以显示编译警告。我所说的“来自构造函数”是指在任何属性初始值设定项表达式或

init
块中,因为这些都是在类构造时调用的。

在这种情况下,您正在调用打开函数

onCreate(). from the superclass constructor, so it is called before anything in the subclass constructor, which is why you have an unexpected null value if you try to access subclass properties in the subclass’s implementation of 
onCreate`。

您的解决方法可能会导致编译器在类构造期间更改某些事件顺序,从而使您的属性值可用。我不会依赖它,因为它不能保证行为,并且可能在未来的编译器版本中发生变化。

目前,您的 open

onCreate()
功能没有做任何有用的事情。您可以简单地删除它并在超类和子类中正常使用 init 块。

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