You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在类外部引用伴生对象内的对象需加Companion.前缀?

Kotlin伴生对象嵌套成员访问行为解析

一、伴生对象内命名object的访问限制

Kotlin的伴生对象本质是类的一个特殊嵌套对象实例,默认名称为Companion。通常我们可以省略Companion直接访问伴生对象的成员属性、函数,这是Kotlin提供的语法糖。

但对于在伴生对象内部定义的嵌套命名对象(如以下代码中的object Obj),它属于伴生对象的嵌套类型,而非伴生对象的直接成员。Kotlin的语法糖不会将这类嵌套类型提升到外部类的级别,因此必须通过Companion前缀来访问这个嵌套对象,否则编译器无法解析引用。

示例代码:

class Cls {
    companion object {
        object Obj {
            val attr = 1
        }
    }
}

fun main() {
   println(Cls.Obj.attr) // 错误:Unresolved reference: Obj —— 嵌套命名对象不属于外部类的直接成员
   println(Cls.Companion.Obj.attr) // 正常 —— 通过伴生对象实例访问其内部嵌套对象
   println(Cls.Obj) // 错误:Unresolved reference: Obj
   println(Cls.Companion.Obj) // 正常
}

二、伴生对象内匿名对象的成员访问限制

当用val Obj = object { ... }的方式定义时,Obj是伴生对象的一个成员属性,因此可以通过Cls.Obj或Cls.Companion.Obj直接访问(符合伴生对象成员的语法糖规则)。

但这里的Obj是匿名对象,其成员(比如attr)仅在定义它的作用域(即伴生对象内部)可见。在外部作用域(如main函数),Obj的静态类型会被编译器推断为Any(如果没有指定显式超类型),因此编译器无法识别attr属性,导致访问报错。

示例代码:

class Cls {
    companion object {
        val Obj = object {
            val attr = 1
        }
    }
}

fun main() {
   println(Cls.Obj.attr) // 错误:Unresolved reference: attr —— 外部无法识别匿名对象的成员
   println(Cls.Companion.Obj.attr) // 错误:Unresolved reference: attr —— 同样受匿名对象的作用域限制
   println(Cls.Obj) // 正常 —— 可以访问伴生对象的成员属性本身
   println(Cls.Companion.Obj) // 正常
}

如果需要在外部访问匿名对象的成员,你可以给匿名对象指定一个显式的超类型(比如定义一个包含attr属性的接口),示例如下:

interface HasAttr {
    val attr: Int
}

class Cls {
    companion object {
        val Obj = object : HasAttr {
            override val attr = 1
        }
    }
}

fun main() {
   println(Cls.Obj.attr) // 正常 —— 此时Obj的静态类型是HasAttr,编译器能识别attr属性
}

内容的提问来源于stack exchange,提问作者Ryan Haining

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 06:36:27