You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin构造函数调用非final函数:抽象函数调用为何结果不符?

解决Kotlin构造函数中调用非final函数的初始化问题

这个问题太典型了——父类构造过程中调用了子类重写的抽象方法,此时子类的成员变量还没完成初始化,自然会拿到类型默认值(比如你例子里的Int默认值0)。这里给你两个最实用的解决思路:

1. 用lazy委托延迟初始化父类属性

把父类里直接调用calculate()的属性改成延迟初始化,这样calculate()会等到第一次访问属性的时候才执行,这时候子类已经完成所有初始化步骤了,能正确拿到x的值:

abstract class Base {
    // 用lazy委托,第一次访问code时才调用calculate
    val code by lazy { calculate() }
    abstract fun calculate(): Int
}

class Derived(private val x: Int) : Base() {
    override fun calculate(): Int = x
}

fun main(args: Array<String>) {
    val i = Derived(42).code // 现在输出42,符合预期
    println(i)
}

2. 重构父类,通过构造参数接收计算结果

换一种设计思路:父类不再依赖抽象方法初始化属性,而是让子类在构造时直接把计算好的值传递给父类。这种方式从根源上避免了构造阶段的跨类方法调用,初始化顺序完全可控:

// 父类直接通过构造参数接收code的值
abstract class Base(val code: Int)

// 子类构造时把x直接传给父类
class Derived(private val x: Int) : Base(x)

fun main(args: Array<String>) {
    val i = Derived(42).code // 输出42
    println(i)
}

如果你的业务逻辑允许,我更推荐第二种方案,因为它的代码更简洁,也不存在任何初始化顺序的隐患。

内容的提问来源于stack exchange,提问作者rosghub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:01:26