kotlin - 如何在有对象作用域的环境中调用非扩展“运行”函数(没有作用域/“对象引用”的函数)?
问题描述
例子:
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
在这种情况下工作。
一个好的答案应该做以下事情之一:
- 解释当名称重载时如何指示编译器调用函数而不是扩展方法;或者
- 解释如何专门针对
run
; 或者 - 解释(理想情况下也是为什么)这是不可能的(最好是有支持的参考资料);或者
- 解释我做错了什么,以防我出错并且整个问题无关紧要(例如,如果我的分析不正确,并且问题不是编译器将调用解释为
run
asthis.run
)。
如果有人有一个上面没有提到的简洁的解决方法,欢迎他们在评论中发布 - 而不是作为答案。
以防万一:我使用的是多平台 Kotlin 1.4.20。
解决方案
如果它在范围内,Kotlin 倾向于接收器重载。解决方案是使用非接收函数的完全限定名称:
kotlin.run { //...
规范在这里解释。
当重载不在同一个包中时,另一个选择是使用import renaming,但在这种情况下这不起作用,因为两个run
函数都在同一个包中。
推荐阅读
- process - 围绕交互式 CLI (mysql) 进程包装 CLI 工具
- php - foreach laravel 总是将最新迭代对象的属性以 post 形式作为路由的参数
- javascript - React JS如何使用会话存储在页面之间传递值
- javascript - 如何为多个表单提交创建粘性进度条?
- mysql - phpmyadmin 创建 ENUM 错误
- c++ - ACM ICPC - 图中的 K 桥
- javascript - jQuery .getJSON() 轮询内存泄漏
- python - 匹配单个字符串中的许多模式
- c - 从 C 编译器理解 MIPS 汇编代码
- jquery - 如何从 jquery .click 事件中排除特定的 div