如何在属性 y 初始化后执行 init 块中的代码

问题描述

在初始化属性 y 之后,我想在我的类 init 块中调用一些代码。我已经用 this::y.isInitialized ... 试过了,但这里的问题是在创建类时,属性没有初始化(它在运行时得到)。

示例类

class Example {
     lateinit var y: String // this gets initialized after the creation of the fragment at a later time

     init {
         if(this::y.isInitialized) {
            doStuff()
         }
     }

}

Szenario

val testObject = Example()
testObject.y = "START INIT CODE" // here it should execute the init block

这甚至可能吗?或者我应该在确保 y 已初始化后使用函数调用更改 init 块?

解决方法

public class User { // Add just the properties you care about public string Id { get; private set; } public string UserName { get; private set; } public string DisplayName { get; private set; } public string Color { get; private set; } public string Email { get; private set; } // Make the default constructor private so instances of this // class can only be created from one of our static methods private User() { } public static User FromTwitch(TwitchUser twitchUser) { return new User { Id = twitchUser.Id,Color = twitchUser.Color,DisplayName = twitchUser.DisplayName,UserName = twitchUser.UserName }; } public static User FromDiscord(DiscordUser discordUser) { return new User { Email = discordUser.Email,UserName = discordUser.Username }; } } 块专门用于实例化时调用的代码,因此它不适用于 init 的东西。

我还必须提到,在我看来,公共 lateinit 是一种巨大的代码气味。没有办法强制外部类在编译时适当地处理它。 lateinit var 适用于仅在某些构建后事件之后才可用(可见)的属性。

假设我们不关心设计问题,您可以解决的一种方法是使用第二个可为空的支持属性。

lateinit
,

你可以这样做:

class Example {

    var y: String = "UNINITIALIZED"
        set(value) {
            if (field == "UNINITIALIZED") doStuff(value)
            field = value
        }

    fun doStuff(y: String) {...}
}

或者如果你需要修改初始值:

class Example {

    var y: String = "UNINITIALIZED"
        set(value) {
            field = if (field == "UNINITIALIZED") doStuff(value) else value
        }

    fun doStuff(y: String): String {...}

}
,

您可以为此使用可观察的属性委托。举个例子:

import kotlin.properties.Delegates

class Example {
    var y: Int? by Delegates.observable(initialValue = null) { _,oldValue,_ ->
        if (oldValue == null) {
            doStuff()
        }
    }

    private fun doStuff() {}
}

如果您需要更复杂的逻辑,比如只允许分配一次属性,您可能需要实现自己的 property delegate,类似于所建议的。