kotlin - Kotlin - var 与对象声明之间的区别
问题描述
和有什么区别
object Foo : Any() { ... }
和
val Foo = object : Any() { ... }
是否存在任何语义和/或逻辑差异,何时应该使用它们?
解决方案
object Foo : Any() { ... }
这是一个对象声明,它声明了一个类似单例的类型
Foo
,其单个实例包含在object
范围内声明的成员,并在首次访问时延迟初始化。它可以在顶层或其他类型内部使用,但不能在函数体内部使用。当在另一个类型中声明时,它仍然只会创建一个对象,而不是每个封闭类型的实例创建一个对象。class Bar { object Foo : Any() { ... } // only one object is created }
对象声明通常用于封装全局单例状态并将相关的公共 API 成员分组。但是,由于
Foo
可以用作普通对象,因此还有更多用例。其中之一是将object
声明作为密封类的子类型。val Foo = object : Any() { ... }
这是一个对象表达式,也可以在函数体内使用。当它被评估时,它每次都会创建一个新对象。特别是,如果它在另一个类型中声明,它将为封闭类型的每个实例创建一个新对象。
class Bar { val foo = object : Any() { ... } // new object for each instance of Bar }
当在顶层声明时,它仍然是一个单例,但它会在第一次访问文件外观类(包含该文件的其他顶层成员)而不是
val
.当您以这种方式声明属性时,您将无法调用在
object
属性范围内添加的成员,而不是对象声明。但是,当用作局部变量时,这样的 aval
将暴露其附加成员。// on top level: val foo = object : Any() { val x = 1 } fun main() { println(foo.x) // error, unresolved reference 'x' val bar = object : Any() { val x = 1 } println(bar.x) // OK }
对属性进行此限制的目的是避免在匿名类(对象表达式被编译到)中使用公共 API,这可能会在下次编译时以不兼容的方式隐式更改。相反,对象声明声明了一个命名类型。
对象表达式和对象声明都可以从类继承并实现接口。当您需要提供不想用类实现的接口实例时,对象表达式特别有用(例如,它是一个不会在其他任何地方使用的临时实现):
// in a library: interface ResponseHandler { fun onSuccess(response: Response): Unit fun onError(exception: Exception): Unit } fun Request.execute(responseHandler: ResponseHandler) { ... }
// your code: val request: Request = ... request.execute(object : ResponseHandler { fun onSuccess(response: Response) { ... } // provide the implementations fun onError(exception: Exception) { ... } // for these two functions })
注意:在这两种情况下,您都可以省略: Any()
,因为Any
它是对象声明和对象表达式的默认超类型。
推荐阅读
- javascript - 共享页面代码是用 jquery 制作的,但在 webview 中不起作用
- embedded - MPU6050s DMP初始化数据是什么意思?
- node.js - 未能正确使用电子打包程序进行代码设计或通过 npm 为基于 Electron 的 macOS 应用程序注入 plist 项目
- javascript - Eslint 强制消耗返回值
- plot - mne.viz.plot_topomap 的颜色条?Python
- reactjs - React 网络摄像头设置超时
- python-3.x - Python Authlib 是否支持解码 AWS Cognito 访问/ID 令牌?
- mysql - 计算一段时间内的俱乐部会员数据(新的、过去的和当前的)
- hex - 计算 shellcode 中的字节数
- javascript - 在输入表单中插入值