isInitialized - lateinit var 的支持字段此时不可访问

Posted

技术标签:

【中文标题】isInitialized - lateinit var 的支持字段此时不可访问【英文标题】:isInitialized - Backing field of lateinit var is not accessible at this point 【发布时间】:2018-05-12 22:33:04 【问题描述】:

我正在尝试检查 lateinit 属性是否已初始化。 在 Kotlin 1.2 中,我们现在有了 isInitialized 方法。当我在声明了 lateinit 属性的类中这样做时,它会起作用。 但是当我尝试从另一个类调用它时,我收到以下警告:

此时无法访问“lateinit var foo: Bar”的支持字段

我的模型类(比如Person)是用 Java 编写的 另外两个类(比如Test1Test2)是用 Kotlin 编写的

例子:

class Test1 
    lateinit var person: Person

    fun method() 
        if (::person.isInitialized) 
            // This works
        
    

-

class Test2 
    lateinit var test1: Test1

    fun method() 
        if (test1::person.isInitialized) 
            // Error
        
    

有没有机会让这个工作?

我目前的解决方法是在 Test1 中创建一个从 person 属性返回 isInitialized 的方法。

fun isPersonInitialized(): Boolean = ::person.isInitialized

//in Test2:
if (test1.isPersonInitialized()) 
    // Works

【问题讨论】:

我不知道答案。但是为什么你使用isInitialized 而不是可空的呢? lateinit show 总是在使用对象之前被初始化。 @Eledgy 您的代码无法编译。您不能将 if 表达式直接放在类主体中。我想你忘了把它包装在一个 init 块中。我知道,这并不能解决您的初始问题。 @Joshua 我有一个人可能还没有被初始化的情况 @WilliMentzel 只是一个例子,我已经把代码放在了一个方法中 @ElegyD 然后,您应该使用Person?。如果您滥用 lateinit,则每次访问人员时都需要一个 if,这会使您返回 Java 并进行空检查。 【参考方案1】:

accepted answer 描述的约束的一个非常简单的解决方法如下:

class LateClass 
    lateinit var thing: Thing
    fun isThingInitialized() = ::thing.isInitialized


class Client 
    val lateClass = LateClass()
    ... things happen ...
    if (lateClass.isThingInitialized() 
        // do stuff with lateClass.thing, safely
    

【讨论】:

非常漂亮和优雅。转换为属性.. val isThingInitialized: Boolean = ::thing.isInitialized @TejasviHegde 不会在创建时将 isThingInitialized 设置为 false,并且考虑到它是不可变的,一旦事物被初始化就永远不会更新为 true? @ThomasSunderland isThingInitialized 不是一成不变的,它是一个函数。 val isThingInitialized: Boolean = ::thing.isInitialized 将始终为 false,因为仅预先计算一次。您可以在此解决方案中创建一个函数,或创建一个惰性字段:val isThingInitialized: Boolean by lazy ::thing.isInitialized @TejasviHegde 使用属性只有在设置 getter 后才能成功。【参考方案2】:

根据docs:

此检查仅适用于词法可访问的属性,即在同一类型或外部类型之一中声明,或在同一文件的顶层声明。

这就是为什么你不能在主函数中检查它的原因。

【讨论】:

在 kotlin v1.3.+ 中仍应考虑这一点 :)【参考方案3】:

我作为 Kotlin 属性的版本。

class LateClass 
    lateinit var thing: Thing
    val isThingInitialized get() = this::thing.isInitialized 

【讨论】:

以上是关于isInitialized - lateinit var 的支持字段此时不可访问的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin类的初始化 ④ ( lateinit 延迟初始化 | ::属性名称.isInitialized 检查属性是否初始化 | lazy 惰性初始化 )

Android开发Kotlin检查lateinit变量是否已初始化的方法

带有 QT 错误的 OpenGL:断言:“QOpenGLFunctions::isInitialized(d_ptr)”。无法创建 OpenGL 上下文

如何检查“lateinit”变量是不是已初始化?

Kotlin中,lateinit 和 lazy{} 的区别

如何检查“lateinit”变量是否已初始化?