【问题标题】:Overload resolution ambiguity. All these functions match重载分辨率歧义。所有这些功能都匹配
【发布时间】:2026-01-09 20:40:01
【问题描述】:

我尝试检查,lateinit 变量是否在使用引用运算符的函数中初始化。在这种情况下,函数名和变量名相同。这样 Kotlin 就会抛出

重载分辨率不明确。所有这些功能都匹配

异常。其实这段代码有什么问题?

class ABC

class MyClass {
    private lateinit var abc: ABC

    fun abc() {
        if(!::abc.isInitialized){
            println("Hello")
        }
    }
}

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    这是一个简单的名称冲突。编译器不知道您指的是方法abc 还是属性abc。重命名可以解决问题:

    class MyClass {
        private lateinit var abc: ABC
    
        fun abcFun() {
            val prop = this::abc
            if (!::abc.isInitialized) {
                println("Hello")
            }
        }
    }
    

    【讨论】:

    • 或调用属性:_abc
    • 知道函数应该有什么目的可能是相关的。
    • @crgarridos 你是什么意思“或”?您仍然进行了重命名,只是不在它的功能中。
    • 我的意思正是你所说的。在我看来,污染私人成员比污染公共 API 更好。但个人喜好问题
    【解决方案2】:

    您可以通过提取变量并明确指定其类型来消除引用的歧义:

    class ABC
    
    class MyClass {
        private lateinit var abc: ABC
    
        fun abc() {
    
            val abc: KProperty0<ABC> = ::abc
            if(!abc.isInitialized){
                println("Hello")
            }
        }
    }
    

    【讨论】:

    • 不幸的是,isInitialized 只能在文字可调用引用上调用,即只能在文字 ::abc 值上调用,而不能在提取到变量的值上调用。
    【解决方案3】:

    问题是您有一个名为 abc 的属性,可以通过调用 Kotlin 属性访问器 this.abc(类似于“getter”)来访问它,并且您定义了另一个具有相同名称的方法,所以它不会t 识别使用语法 ::abc 引用哪一个。

    IDE 的错误消息也说明了这一点:

    重载分辨率不明确。所有这些功能都匹配:

    • private final lateinit var abc: ABC 定义在 MyClass 中
    • public final fun abc():MyClass 中定义的单元

    【讨论】:

    • 有没有其他方法可以解决这个问题
    • 我会说你需要重命名你的方法/属性。为什么你希望他们有相同的名字?只是为了有一个自定义的吸气剂?如果是这种情况,您可以按照建议 here 创建自定义支持属性
    • 我觉得和getter无关,也会是getAbc()
    • 由于属性定义为private,所以字节码中不会有getAbc()。因此,“getter”是指 Kotlin 获取属性值的方式(在本例中为 this.abc)。我会更新我的答案以使其更清楚
    • 我明白了,这是真的:)
    【解决方案4】:

    如果您在没有引用语法的情况下访问 MyClass 实例上的函数 abc 或属性 abc,它实际上会起作用,尽管我不推荐它。见这里:

    class ABC
    
    class MyClass{
        private lateinit var abc: ABC
    
        fun abc(){
            abc
        }
    }
    
    fun main(args: Array<String>) {
      val c = MyClass()
      c.abc()
    }
    

    这段代码编译没有任何问题。

    但这不是你想要的。创建一个支持字段 _abc 并通过没有支持字段 abc 的属性访问它。这样,如果_abc 尚未初始化,您可以返回ABC 的默认实例。

    class MyClass {
    
        private lateinit var _abc: ABC
    
        val abc: ABC get() {
            if(!::_abc.isInitialized){
                println("Uninitialized")
                return ABC() // some default instance
            }
            println("Initialized")
            return _abc
        }
    
        fun initABC() {
            _abc = ABC()
        }
    } 
    
    fun main(args: Array<String>) {
      val c = MyClass()
      c.abc
      c.initABC()
      c.abc
    }
    

    输出:

    未初始化
    已初始化

    【讨论】:

      最近更新 更多