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

如何确保Kotlin子类完成初始化后再执行父类的excitingInit()方法?

Kotlin中确保子类完全初始化后调用初始化方法

问题分析

Kotlin的初始化顺序为父类属性初始化 → 父类init块 → 子类属性初始化 → 子类init块,父类init块调用子类重写的excitingInit()时,子类属性还未完成初始化,因此输出null initialized。而Swift的初始化顺序与Kotlin相反,子类先完成属性初始化再调用父类构造,所以原逻辑在Swift中可正常运行。

解决方案

我们可以通过父类提供工厂方法的方式,先完成整个对象的初始化(包括父类和子类),再调用excitingInit(),无需子类额外编写init块或构造方法,使用者只需通过工厂方法创建对象即可。

修改后的代码

interface ExcitingInitialize {
    fun excitingInit()
}

abstract class Parent : ExcitingInitialize {
    // 定义工厂方法,创建实例后自动调用初始化方法
    companion object {
        inline fun <reified T : Parent> create(): T {
            val instance = T::class.java.getDeclaredConstructor().newInstance()
            instance.excitingInit()
            return instance
        }
    }
}

class Child : Parent() {
    val myName: String = "Child"

    override fun excitingInit() {
        println("${myName} initialized.")
    }
}

fun main() {
    val p1 = Parent.create<Child>() // 输出"Child initialized."
    p1.excitingInit() // 输出"Child initialized."
}

方案说明

  1. 父类通过companion object提供泛型工厂方法create(),利用反射创建子类实例。
  2. 实例创建完成后(此时父类和子类的所有属性、init块都已执行完毕),再调用excitingInit(),确保子类属性已就绪。
  3. 子类无需修改任何初始化逻辑,保持原有代码即可;使用者只需调用Parent.create<Child>()创建对象,无需手动调用初始化方法。

另一种可选方案(修改子类属性)

如果允许修改子类的属性定义,可以使用lazy延迟初始化属性,这样在父类init块调用excitingInit()时,属性会被自动初始化:

class Child : Parent() {
    // 使用lazy延迟初始化属性
    val myName by lazy { "Child" }

    override fun excitingInit() {
        println("${myName} initialized.")
    }
}

这种方案无需修改父类,但需要子类将属性改为lazy初始化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:05:14