首页 > 解决方案 > 如何在有对象作用域的环境中调用非扩展“运行”函数(没有作用域/“对象引用”的函数)?

问题描述

例子:

data class T(val flag: Boolean) {
    constructor(n: Int) : this(run {
        // Some computation here...
        <Boolean result>
    })
}

在此示例中,自定义构造函数需要运行一些计算以确定将哪个值传递给主构造函数,但编译器不接受run, 引用Cannot access 'run' before superclass constructor has been called,如果我理解正确,这意味着而不是将其解释为非-extension 运行(在https://kotlinlang.org/docs/reference/scope-functions.html#function-selection中没有对象引用的变),它将其解释为对(在上表) - 这是无效的,因为对象尚未完全实例化。this.run

为了让编译器知道我的意思run是不是扩展方法且不占用范围的函数,我该怎么做?

澄清:我对所问问题的答案感兴趣,而不是解决方法。

我可以想到几种解决方法 - 以一种无需调用即可按预期工作的方式重写此代码的方法run:将代码提取到函数中;将其重写为(可能是高度嵌套的)let表达式;删除run并调用 lambda(()在它之后)(有趣的是,IntelliJ IDEA 将其标记为Redundant lambda creation并建议为Inline the body,这会恢复非编译run)。但问题在于如何在不使用的情况下重写run它——而是如何run在这种情况下工作。

一个好的答案应该做以下事情之一:

如果有人有一个上面没有提到的简洁的解决方法,欢迎他们在评论中发布 - 而不是作为答案。

以防万一:我使用的是多平台 Kotlin 1.4.20。

标签: kotlinextension-methodsoverload-resolution

解决方案


如果它在范围内,Kotlin 倾向于接收器重载。解决方案是使用非接收函数的完全限定名称:

kotlin.run { //...

规范在这里解释。

当重载不在同一个包中时,另一个选择是使用import renaming,但在这种情况下这不起作用,因为两个run函数都在同一个包中。


推荐阅读