【问题标题】:Kotlin - Property must be initialized or be abstract even if there is an init() functionKotlin - 即使有 init() 函数,属性也必须被初始化或抽象
【发布时间】:2017-11-06 14:31:43
【问题描述】:

我已使用 Android Studio 3.0 将此代码从 Java 转换为 Kotlin

internal var background: Drawable
internal var xMark: Drawable

private fun init() {
    background = ColorDrawable(Color.RED)
    xMark = ContextCompat.getDrawable(this@Subscriptions_main, R.drawable.delete)
}

在第 1 行和第 2 行出现错误:

属性必须被初始化或者是抽象的

即使它将在 init 函数中初始化。

正在写:

internal var background: Drawable? = null
internal var xMark: Drawable? = null

可行且有效的解决方案?还有其他更好的方法吗?

【问题讨论】:

  • 你可以使用lateinit关键字
  • 谢谢这个工作,如果你愿意的话,写一个答案。它对其他用户也很有用
  • 太好了,很高兴为您提供帮助;)
  • 不要盲目使用lateinit,了解它的作用以及为什么它可能不是你想要的。
  • init() 只是一个函数,不能保证在访问属性之前调用它。

标签: android initialization kotlin


【解决方案1】:

在使用lateinit 之前,您必须了解它的含义。

您的变量未正确初始化。解决该问题的各种方法:

  • 初始化构造函数中的变量或适当的init 块(不是您声明的私有函数)
  • 在声明变量的同时初始化变量
  • 稍后初始化变量并让 Kotlin 知道(这是 lateinit 关键字)

这 3 个选项并不等效,根据您的代码,前两个选项可能比第三个更合适。

lateinit 如果您在变量实际初始化之前访问这些变量,将会使您的应用崩溃。

【讨论】:

    【解决方案2】:

    init blocks 不是函数,只需删除private fun 部分和括号:

    internal var background: Drawable
    internal var xMark: Drawable
    
    init {
        background = ColorDrawable(Color.RED)
        xMark = ContextCompat.getDrawable(this@Subscriptions_main, R.drawable.delete)
    }
    

    【讨论】:

      【解决方案3】:

      您需要lateinit 关键字。检查the docs。

      【讨论】:

      • 这样就解决了问题……直到代码路径改变,变量在被初始化之前被访问。我们没有足够的代码来知道 lateinit 是否合适,或者在构造函数/声明中初始化是否更好。
      • 好吧,在这种情况下,它适用于 OP...但是好吧,你是对的。
      • OMG,OMG,永远不要使用 FEATURE XYZZY,因为它有一个 PITFALL 很少有帮助(有一些语言特性实际上不应该使用,但它们很少见。)lateinit 是在语言中是有原因的。只要答案提到了陷阱(或者在这种情况下说“阅读文档”),它就会有所帮助。
      猜你喜欢
      • 2016-02-24
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多