Как реализовать ленивое свойство в Котлине, которое требует другого свойства?

Мне нужен прямоугольник, который нужно инициализировать при вызове.

Вот мой код;

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) } что говорит это;

Переменная textWidth должна быть инициализирована. Переменная textHeight должна быть инициализирована.

Но я уже инициализирую их на init{} кодовый блок.

Что я делаю неправильно?

1 ответ

Решение

В kotlin вы должны инициализировать переменную перед ее использованием. Вы используете ленивый инициализатор для Rectangle, но компилятор не знает статуса textWidth и textHeight

Так класс выглядит так

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) }

Обновлено:-Почему порядок инициализации имеет значение здесь?

Мы можем назвать это утомленным поведением Нуль-Сафти из Котлина. Когда мы меняем порядок блока init и объявления переменных, мы нарушаем это правило.

Из официальной документации Котлина:-

Система типов Kotlin предназначена для исключения исключений NullPointerException из нашего кода. Единственными возможными причинами NPE могут быть

  1. Явный вызов для выброса NullPointerException();

  2. Использование!! оператор, который описан ниже;

  3. Внешний Java-код вызвал это;

  4. Существует некоторая несогласованность данных в отношении инициализации (где-то используется неинициализированное это, доступное в конструкторе).

Помимо этих четырех условий, он всегда гарантирует, что переменная инициализируется во время компиляции. так же, как и в нашем случае, он просто гарантирует, что используемая переменная должна быть инициализирована перед использованием.

Другие вопросы по тегам