kotlin - 如何访问顶级对象的字段?
问题描述
当我这样做时
val data = object {
val field = 5
}
fun main(){
println(data.field) // throws
}
它抛出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
}
我不明白,为什么 Kotlin 不允许我使用顶级对象的属性?我认为这object
就像类对象一样,但是匿名(没有类),data
并且data7
上面的示例之间应该没有区别。但似乎有区别。
解决方案
这在Language Specification的“Object Literals”部分中有记录,关于对象声明和匿名对象(对象文字创建的东西)之间的区别。
常规对象声明和匿名对象之间的主要区别在于其类型。匿名对象的类型是一种特殊类型,仅在声明它的范围内可用(并且可见)。它类似于常规对象声明的类型,但由于它不能在声明范围之外使用,因此具有一些有趣的效果。
您的data
此处被认为已超出“文件顶层”的声明范围,因为它是公开的。您可以从其他文件的顶级范围访问它。
注意:在这种情况下,如果相应的值被声明为非私有全局或分类器范围属性,则立即执行“转义当前范围”,因为它们是外部可访问接口的一部分。
标记它private
会修复它。错误的原因是:
当匿名对象类型的值超出当前范围时:
- 如果该类型只有一个声明的超类型,它会隐式向下转换为这个声明的超类型;
- 如果该类型有多个声明的超类型,则必须隐式或显式强制转换为范围外可见的任何合适类型,否则会出现编译时错误。
这里,超类型是隐式Any
的,所以类型 data
是Any
,显然field
类型上没有Any
。
另一方面,data4
还没有转义当前范围,因为它是main
函数语句范围的本地。您无法从其他范围访问它。
另请参阅规范中的出色示例。
推荐阅读
- c# - 如何将列表中的对象传递给另一个控制器索引函数?
- raspberry-pi - cpufreq - 无法更改“scaling_available_frequencies”
- d3.js - 如何将svg的宽度和高度设置为等于它的g?
- c++ - 内存分配 wxWidgets
- typescript - Youtube iframe 需要不在我的打字稿定义中的属性
- angular - 单元测试 - Angular 6
- excel-formula - 总结所有新的动态行记录excel表
- java - Android Set不会删除arraylist中选中然后未选中的值
- javascript - 如何使用 Firebase 对数据进行排序?
- vuejs2 - 使用 bootstrap-vue 对 b-table 中的 b-input 进行 Vue 数据绑定