Как реализовать ленивое свойство в Котлине, которое требует другого свойства?
Мне нужен прямоугольник, который нужно инициализировать при вызове.
Вот мой код;
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 могут быть
Явный вызов для выброса NullPointerException();
Использование!! оператор, который описан ниже;
Внешний Java-код вызвал это;
Существует некоторая несогласованность данных в отношении инициализации (где-то используется неинициализированное это, доступное в конструкторе).
Помимо этих четырех условий, он всегда гарантирует, что переменная инициализируется во время компиляции. так же, как и в нашем случае, он просто гарантирует, что используемая переменная должна быть инициализирована перед использованием.