如何访问顶级对象的字段?

Dmi*_*nko 6 kotlin

当我这样做时

val data = object {
    val field = 5
}

fun main(){
    println(data.field)  // throws
}
Run Code Online (Sandbox Code Playgroud)

它抛出Unresolved reference: field.

但这一切都没问题:

val field = 6

class Data(val field: Int = 7)
val data7 = Data()

fun main(){
    val data4 = object {
        val field = 4
    }
    println(field)  // ok
    println(data4.field)  // ok
    println(data7.field)  // ok
}
Run Code Online (Sandbox Code Playgroud)

我不明白,为什么 Kotlin 不允许我使用顶级对象的属性?我认为这object就像类对象一样,但匿名(没有类)data并且data7在上面的示例中和之间应该没有区别。但是好像有区别。

Swe*_*per 8

这记录在语言规范的“对象文字”部分,关于对象声明和匿名对象(对象文字创建的东西)之间的区别。

\n
\n

常规对象声明和匿名对象之间的主要区别在于其类型。匿名对象的类型是一种特殊类型,仅在声明它的范围内可用(且可见)。它类似于常规对象声明的类型,但由于它不能在声明范围之外使用,因此具有一些有趣的效果。

\n
\n

您的data此处被认为逃脱了“文件顶层”的声明范围,因为它是公共的。您可以从其他文件的顶级范围访问它。

\n
\n

注意:在这种情况下,如果相应的值被声明为非私有全局或分类器范围属性,则立即执行\xe2\x80\x9cecaping当前范围\xe2\x80\x9d,因为这些是外部可访问接口的一部分。

\n
\n

标记它就private可以修复它。错误的原因是:

\n
\n

当匿名对象类型的值脱离当前范围时:

\n
    \n
  • 如果该类型只有一个声明的超类型,则它会隐式向下转换为该声明的超类型;
  • \n
  • 如果该类型有多个声明的超类型,则必须隐式或显式转换为范围外可见的任何合适的类型,否则会出现编译时错误。
  • \n
\n
\n

这里,超类型是隐式的Any,所以类型上 data是,而类型上Any显然没有。fieldAny

\n

另一方面,data4没有转义当前作用域,因为它是main函数的语句作用域的本地范围。您无法从其他范围访问它。

\n

另请参阅规范中的精彩示例。

\n