【问题标题】:Must be initialized error in val variable必须在 val 变量中初始化错误
【发布时间】:2020-02-20 12:24:01
【问题描述】:

以下代码报告property must be initialized or be abstract错误。

// MyApi.kt
interface MyApi {

    ...
}

// MyFetch.kt
class MyFetch {

    private val myApi: MyApi  // <- this line

    ...
}

在可变变量中可以使用lateinit语句,但是在val中应该如何预定义呢?

【问题讨论】:

  • 把它放在构造函数中,以便在初始化的类中传递。
  • @Tenfour04 是否意味着我需要在 init {} 构造中使用 myApi?
  • 看我的回答..
  • @ccd 这意味着您需要在 myApi 属性上实现接口才能初始化 MyFetch 类?或者进行某种委托。

标签: android kotlin


【解决方案1】:

你可以使用惰性,或者让它可以为空

private val myApi: MyApi? = null

【讨论】:

    【解决方案2】:

    关注点分离设计模式倾向于将值传递给构造函数。因此,其他一些实例化您的 MyFetch 类的类也会实例化您的 MyApi 实例并将其传递给构造函数:

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

    但是你也可以在类中初始化它。如果 MyApi 与 MyClass 的行为紧密耦合,这将是有意义的:

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

    在这三种情况中的任何一种情况下,只读val 属性的值必须在构造函数中、与声明内联或在init 块中分配。唯一的其他选择是使用属性委托。

    【讨论】:

      【解决方案3】:

      您实际上必须在创建对象时在变量声明本身或init{} 块中初始化变量,因为 Kotlin 中没有 preinit null 类型。

      由于您的变量是val 而不是var,因此您无法在创建后设置它,因此没有必要创建变量。

      如果您打算稍后初始化变量但只初始化一次,请查看以下答案:https://stackoverflow.com/a/48445081/11377112 这是由这样的委托完成的:

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

      现在你可以通过委托来委托变量

      var property: Int by InitOnceProperty()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-31
        相关资源
        最近更新 更多