3

Following code report property must be initialized or be abstract error.

// MyApi.kt interface MyApi { ... } // MyFetch.kt class MyFetch { private val myApi: MyApi // <- this line ... } 

It can use lateinit statement in mutable variable, but how should I predefined in val?

6
  • Check this: kotlinlang.org/docs/tutorials/kotlin-for-py/… Commented Feb 20, 2020 at 12:28
  • Put it in the constructor so it can be passed in the the class is initialized. Commented Feb 20, 2020 at 12:38
  • @Tenfour04 is it mean I need using myApi in init {} construct? Commented Feb 20, 2020 at 12:48
  • See my answer.. Commented Feb 20, 2020 at 13:20
  • @ccd it means you need to have an implementation of interface being on the myApi property in order to initialize MyFetch class?, or be some sort of delegated. Commented Feb 20, 2020 at 15:06

3 Answers 3

1

You can use lazy, or make it nullable

private val myApi: MyApi? = null 
Sign up to request clarification or add additional context in comments.

Comments

1

The Separation of Concerns design pattern would favor passing a value to the constructor. So some other class that instantiates your MyFetch class would also instantiate your MyApi instance and pass it to the constructor:

class MyClass(val myApi: MyApi){ } //Some higher level class: val myAPI = object: MyApi { //... } val myClass = MyClass(myApi) 

But you can also just initialize it from within the class. This would make sense if MyApi is tightly coupled to the behavior of MyClass:

class MyClass { val myApi = object: MyApi { //... } } // or class MyClass { val myApi: MyApi init { myApi = object: MyApi { //... } } } 

In any of the three cases, a value of read-only val property has to be assigned in either the constructor, inline with the declaration, or in an init block. The only other option is to use a property delegate.

Comments

1

You actually have to initialize the variable on the time of object creation in the variable declairation itself or in the init{} block, since there is no preinit null type in the Kotlin.

And since your variable is val not var you cannot set it after created so there's no point of creating the variable.

If you meant to initialize the variable later on but only once, check this answer: https://stackoverflow.com/a/48445081/11377112 This is done by delegation like this:

class InitOnceProperty<T> : ReadWriteProperty<Any, T> { private object EMPTY private var value: Any? = EMPTY override fun getValue(thisRef: Any, property: KProperty<*>): T { if (value == EMPTY) { throw IllegalStateException("Value isn't initialized") } else { return value as T } } override fun setValue(thisRef: Any, property: KProperty<*>, value: T) { if (this.value != EMPTY) { throw IllegalStateException("Value is initialized") } this.value = value } } 

Now you can delegate the variable by the delegate

var property: Int by InitOnceProperty() 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.