如何确保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." }
方案说明
- 父类通过
companion object提供泛型工厂方法create(),利用反射创建子类实例。 - 实例创建完成后(此时父类和子类的所有属性、init块都已执行完毕),再调用
excitingInit(),确保子类属性已就绪。 - 子类无需修改任何初始化逻辑,保持原有代码即可;使用者只需调用
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
相关产品推荐
相关产品推荐

