如何在 Kotlin 中实现一个需要另一个 属性 的惰性 属性?

How to implement a lazy property in Kotlin that requires another property?

我需要一个需要在调用时初始化的矩形。

这是我的代码;

class EpheButton private constructor(
    private val text: String,
    private val x: Float,
    private val y: Float,
    private val projectionMatrix: Matrix4) : Disposable {
private val spriteBatch: SpriteBatch = SpriteBatch()
private val bitmapFont: BitmapFont = BitmapFont()
private val shapeRenderer: ShapeRenderer = ShapeRenderer()

private val textWidth: Float
private val textHeight: Float
private val rectangle :Rectangle by lazy { Rectangle(x, y, textWidth, textHeight) }

init {
    bitmapFont.data.setScale(2f)
    bitmapFont.region.texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
    bitmapFont.color = Color.BLUE
    val layout = GlyphLayout()
    layout.setText(bitmapFont, text)
    textWidth = layout.width
    textHeight = layout.height
}

我收到关于 private val rectangle :Rectangle by lazy { Rectangle(x, y, textWidth, textHeight) } 行的错误,上面写着;

Variable 'textWidth' must be initialized Variable 'textHeight' must be initialized

但我已经在 init{} 代码块上初始化它们了。

我做错了什么?

在 kotlin 中,您必须在使用变量之前对其进行初始化,您正在为 Rectangle 使用延迟初始化程序,但编译器不知道 textWidth 和 [=23 的状态=]文字高度

所以 class 看起来像这样

class EpheButton private constructor(
    private val text: String,
    private val x: Float,
    private val y: Float,
    private val projectionMatrix: Matrix4) : Disposable {
private val spriteBatch: SpriteBatch = SpriteBatch()
private val bitmapFont: BitmapFont = BitmapFont()
private val shapeRenderer: ShapeRenderer = ShapeRenderer()

private val textWidth: Float
private val textHeight: Float
init {
    bitmapFont.data.setScale(2f)
    bitmapFont.region.texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
    bitmapFont.color = Color.BLUE
    val layout = GlyphLayout()
    layout.setText(bitmapFont, text)
    textWidth = layout.width
    textHeight = layout.height
}
private val rectangle :Rectangle by lazy { Rectangle(x, y, textWidth, textHeight) }

已更新:- 这里为什么要考虑初始化顺序?

我们可以将这种奇怪的行为称为 Kotlin 的 Null-Safty。当我们改变 init blockvariable declaration 的顺序时,我们就打破了这条规则。

From Kotlin official documentaion :-

Kotlin's type system is aimed to eliminate NullPointerException's from our code. The only possible causes of NPE's may be

  1. An explicit call to throw NullPointerException();

  2. Usage of the !! operator that is described below;

  3. External Java code has caused it;

  4. There's some data inconsistency with regard to initialization (an uninitialized this available in a constructor is used somewhere).

除这四个条件外,它始终确保在编译时初始化变量。与我们的情况一样,它只是确保使用的变量必须在使用之前进行初始化。