有没有一种更简洁的方法可以稍后在代码中设置顶级变量而不使其成为 lateinit var?

Is there a cleaner way to set a top-level variable later in code without making it a lateinit var?

所以我想要实现的是稍后在 main 函数中设置顶级变量,但我不想让它成为一个 lateinit var,这肯定会破坏 Extension可变功能。

例如,此代码不起作用,因为扩展变量不支持 lateinit 修饰符:

lateinit var Dispatchers.Konvironment: MainCoroutineDispatcher
    private set

fun main() {
    ...
    Dispatchers.Konvironment = ArbitraryMainDispatcher(Thread.currentThread()) { queue.add(it) }
    ...
}

所以我最终想到的是使用虚拟变量并实现 val 变量的 getter。

val Dispatchers.Konvironment: MainCoroutineDispatcher
    get() = dispatcher

private lateinit var dispatcher: MainCoroutineDispatcher

fun main() {
    ...
    dispatcher = ArbitraryMainDispatcher(Thread.currentThread()) { queue.add(it) }
    ...
}

但这肯定不是干净的方法。在顶层结构中创建多个变量看起来很难看(大概)不是很干净的架构。

那么是否有任何可能的干净解决方法?有点像延迟初始化,由一些代表或其他人进行。

嗯,部分回答你的问题:

var Dispatchers.Konvironment: MainCoroutineDispatcher
    get() = dispatcher
    private set(value) {
        dispatcher = value
    }

private lateinit var dispatcher: MainCoroutineDispatcher

fun main() {
    ...
    Dispatchers.Konvironment = ArbitraryMainDispatcher(Thread.currentThread()) { queue.add(it) }
    ...
}

将为您提供所需的赋值方式。但是,没有办法摆脱这个额外的 lazyinit 变量。

扩展只不过是静态方法的一些 Kotlin 语法糖,这些静态方法将扩展 class 的实例作为参数之一,并执行一些操作。如果您熟悉 Java,那么,例如,这些扩展:

// Extensions.kt

fun Foo.extendedAction() {
    println(this)
}

var Foo.extendedBar: Bar
    get() = this.bar
    set(value) {
        this.bar = value
    }

Java:

中的这些方法
public class ExtensionsKt {
    public static final void extendedAction(Foo foo) {
        System.out.println(foo);
    }

    public static final Bar getExtendedBar(Foo foo) {
        return foo.getBar();
    }

    public static final Bar setExtendedBar(Foo foo, Bar bar) {
        foo.setBar(bar);
    }
}

从上面得出的结论是,扩展实际上并没有 添加 任何扩展 classes 的签名,它们只是 decorate 它们具有额外的功能。或者,如 docs:

Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.

所以你可以看到,除非 dispatcher 以某种方式已经存在于 Dispatchers 中,否则你无法在不提供外部 "backing" 变量的情况下做你想做的事情,该变量的值实际上可以是由扩展程序引用。