在超类的初始化中使用变量时,覆盖变量会创建一个NPE

假设我们有以下设置:

open class Foo(open val img: Image) { val use = img.graphics } class Bar(override val img: BufferedImage) : Foo(img) 

初始化时,使用img.width创建一个NPE。 我认为问题在于,显然即使img直接在Bar的构造函数中传递,当它在Foo中使用时,它并不指向它,而是指向Bar类中的重写变量。 我怎样才能避免这一点?

这种行为是由img的getter被覆盖并返回不同字段的值(因为Bar用不同的类型覆盖img ,它需要创建一个BufferedImage类型的附加字段)的事实造成的。 Foo构造函数在Bar分配该字段之前执行。

一般来说,你应该避免在你的类的初始化逻辑中使用打开的成员,因为它们可能在子类中被覆盖,并且可能依赖于在超类初始化的时候还没有正确初始化的状态。

对于你的具体情况,在Foo构造函数中创建一个简单的参数,并明确地使用该参数:

 open class Foo(img: Image) { open val img = img val use = img.graphics }