有什么区别
object Foo : Any() { ... }
Run Code Online (Sandbox Code Playgroud)
和
val Foo = object : Any() { ... }
Run Code Online (Sandbox Code Playgroud)
是否存在任何语义和/或逻辑差异?何时应该使用它们?
object Foo : Any() { ... }
这是一个对象声明,它声明一个类似单例的类型Foo,其单个实例包含在object范围内声明的成员,并在第一次访问时延迟初始化。它可以在顶层或其他类型内部使用,但不能在函数体内使用。当在另一个类型中声明时,它仍然只会创建一个对象,而不是每个封闭类型的实例创建一个对象。
class Bar {
object Foo : Any() { ... } // only one object is created
}
Run Code Online (Sandbox Code Playgroud)
对象声明通常用于封装全局单例状态并对相关的公共 API 成员进行分组。然而,由于Foo可以作为普通对象使用,因此还有更多用例。其中之一是声明为密封类object的子类型。
val Foo = object : Any() { ... }
这是一个对象表达式,它也可以在函数体内使用。当它被评估时,它每次都会创建一个新对象。特别是,如果它在另一个类型中声明,它将为封闭类型的每个实例创建一个新对象。
class Bar {
val foo = object : Any() { ... } // new object for each instance of Bar
}
Run Code Online (Sandbox Code Playgroud)
当在顶层声明时,它仍然是一个单例,但它将在第一次访问文件外观类(包含该文件的其他顶级成员)时初始化,而不是访问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
}
Run Code Online (Sandbox Code Playgroud)
对属性进行此限制的目的是避免在匿名类(对象表达式编译到的对象)中使用公共 API,这些 API 可能在下次编译时以不兼容的方式隐式更改。相反,对象声明声明一个命名类型。
对象表达式和对象声明都可以从类继承并实现接口。当您需要提供不想用类实现的接口实例时,对象表达式特别有用(例如,它是一个不会在其他任何地方使用的临时实现):
// in a library:
interface ResponseHandler {
fun onSuccess(response: Response): Unit
fun onError(exception: Exception): Unit
}
fun Request.execute(responseHandler: ResponseHandler) { ... }
Run Code Online (Sandbox Code Playgroud)
// your code:
val request: Request = ...
request.execute(object : ResponseHandler {
fun onSuccess(response: Response) { ... } // provide the implementations
fun onError(exception: Exception) { ... } // for these two functions
})
Run Code Online (Sandbox Code Playgroud)注意:在这两种情况下,您都可以省略: Any(),因为这Any是对象声明和对象表达式的默认超类型。
| 归档时间: |
|
| 查看次数: |
254 次 |
| 最近记录: |