Исключение NullPointerException при попытке доступа к унаследованному полю

Я получаю NPE при попытке доступа к переопределенной переменной в родительском классе

java.lang.NullPointerException: Attempt to get length of null array at app.deadmc.materiallivewallpaper.model.Square.<init>(Square.kt:29) at app.deadmc.materiallivewallpaper.model.Cube.<init>(Cube.kt:8) at app.deadmc.materiallivewallpaper.renderer.MaterialRenderer.onSurfaceCreated(MaterialRenderer.kt:40) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1548) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1286) 

Я покажу упрощенный код для решения проблемы

У меня есть класс для рисования квадрата

 open class Square(renderer: ReadyRenderer) { val COORDS_PER_VERTEX = 3 open val triangleCoords = floatArrayOf( //first triangle -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, //second triangle -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f) private val vertexCount:Int = triangleCoords.size / COORDS_PER_VERTEX init { val bb = ByteBuffer.allocateDirect( triangleCoords.size * 4) //other code } } 

Квадрат работает правильно, но теперь я хочу нарисовать Cube, поэтому я просто наследую от Square и добавляю больше координат

 open class Cube(renderer: ReadyRenderer):Square(renderer) { val size = 1.0f override val triangleCoords = floatArrayOf( //front side // Triangle 1 -size, size, size, // top-left -size, -size, size, // bottom-left size, -size, size, // bottom-right // Triangle 2 size, -size, size, // bottom-right size, size, size, // top-right -size, size, size, // top-left //and then back side, left, top, right with same way ) } 

Кажется, логика, не так ли? Все переменные имеют значения, и для NPE не должно быть места.

Но когда я пытаюсь создать экземпляр Cube

  val cube = Cube(this@MaterialRenderer) 

Я поймаю NullPointerException в квадратном классе в этой строке:

 private val vertexCount:Int = triangleCoords.size / COORDS_PER_VERTEX 

Даже если я присваиваю значение прямо как

 private val vertexCount:Int = 2 

Я получу NPE в классе Square внутри блока init в этой строке:

 val bb = ByteBuffer.allocateDirect( triangleCoords.size * 4) 

Итак, у меня есть 2 вопроса:

1. Как я могу исправить это и все еще использовать наследование?

2. Должно ли это так работать?

Если вы посмотрите на редактор, он фактически предупредил вас, используя свойство non-final в конструкторе. Это происходит потому, что, когда вы создаете Cube , сначала необходимо создать Square . Когда Square создается, Cube не инициализируется. ( triangleCoords – null) Поэтому triangleCoords.size будет генерировать исключение.

Как я могу исправить это и все еще использовать наследование?

Вы должны передать его как параметр.

 open class Square(protected val triangleCoords: FloatArray = floatArrayOf( //first triangle -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, //second triangle -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f)) { val COORDS_PER_VERTEX = 3 private val vertexCount: Int = triangleCoords.size / COORDS_PER_VERTEX init { val bb = ByteBuffer.allocateDirect( triangleCoords.size * 4) //other code } } open class Cube(val size: Float = 1.0f) : Square(floatArrayOf( //front side // Triangle 1 -size, size, size, // top-left -size, -size, size, // bottom-left size, -size, size, // bottom-right // Triangle 2 size, -size, size, // bottom-right size, size, size, // top-right -size, size, size, // top-left //and then back side, left, top, right with same way )) { } 

Если вы считаете, что это уродливо, вы можете написать фабричный метод и передать массив через параметр частному конструктору.

Должно ли это так работать?

да