Object Kotlin中嵌套对象声明的可访问性不一致

Object Kotlin中嵌套对象声明的可访问性不一致,object,kotlin,compiler-errors,compiler-bug,language-specifications,Object,Kotlin,Compiler Errors,Compiler Bug,Language Specifications,考虑以下Kotlin代码: object Domain { val name = "local" val location = object { val city = "Pittsburgh" val state = "Pennsylvania" } } 虽然此定义有效并可编译,但以下行失败: val x = Domain.location.city // Error:(30, 27) Kotlin: Unresolved reference: city 但是

考虑以下Kotlin代码:

object Domain {
  val name = "local"
  val location = object {
     val city = "Pittsburgh"
     val state = "Pennsylvania"
  }
}
虽然此定义有效并可编译,但以下行失败:

val x = Domain.location.city // Error:(30, 27) Kotlin: Unresolved reference: city
但是,如果我们将上述定义改写如下:

object City {
    val city = "Pittsburgh"
    val state = "Pennsylvania"
}
object Domain {
    val name = "local"
    val location = City
}

val x = Domain.location.city    // works fine

我的问题:根据语言规范,这真的是正确的行为吗?这似乎不合理,也不一致。如果不将每个子对象分解为顶级声明,则很难声明复杂的单例对象声明。使用此语法时,编译器似乎正在创建匿名类型,但是,当定义位于嵌套上下文中时,赋值的类型始终为
object
。这几乎像是编译器中的一个类型推断错误。我遗漏了什么?

创建匿名对象所做的就是创建一个扩展任何对象的类。由于除了超类(在本例中为Any)之外,无法提供任何类型信息,因此该超类中未声明的所有字段都将不可见


通过创建命名对象栏,将生成类栏以及对字段的引用,这就是为什么在这种情况下这些字段是可见的。

进一步查看后,创建嵌套对象声明的预期方式如下:
object Foo{val x;object Bar{val y}
,由于另一种语法存在并产生了一些无用的行为,所以它似乎要么编译成等价的代码,要么被禁止;奇怪的是,如果像我在上面的第二个示例中那样声明它们(两个顶级对象,第二个引用第一个),将保留足够的类型信息,以允许引用内部对象的字段。这似乎不一致,也出乎意料。另外,虽然替代语法可以工作,并且比分解对象更为详细,但它的缺点是,使用反射遍历匿名对象成员的代码看不到嵌套对象属性(因为它们不是属性,而是嵌套类型)。我不知道为什么您认为引用顶级对象不会保留足够的信息以允许访问其字段。因为它是一个命名对象,所以它将有一个生成的类文件,保留所有字段信息并允许访问。创建匿名类时,生成的类文件不保留超类型信息以外的任何信息。