Kotlin object expressions and object declarations
Kotlin uses object expressions and object declarations to create an object of a class that has slightly changed a certain class, and does not need to declare a new subclass
Object expression
An object of an anonymous inner class is implemented through object expressions for use in method parameters
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) {
// ...
}
})
Objects can inherit from a base class or implement other interfaces
open class A(x: Int) {
public open val y: Int = x
}
interface B {……}
val ab: A = object : A(1), B {
override val y = 15
}
If the supertype has a constructor, you must pass parameters to it. Multiple supertypes and interfaces can be separated by commas.
Through the object expression, an object can be directly obtained through the definition of the class
fun main(args: Array<String>) {
val site = object {
var name: String = "菜鸟教程"
var url: String = "www.runoob.com"
}
println(site.name)
println(site.url)
}
Note that anonymous objects can be used as types declared only in local and private scopes. If you use an anonymous object as the return type of a public function or as the type of a public property, then the actual type of the function or property will be the supertype declared by the anonymous object. If you do not declare any supertype, it will be Any. Members added in anonymous objects will not be accessible
class C {
// 私有函数,所以其返回类型是匿名对象类型
private fun foo() = object {
val x: String = "x"
}
// 公有函数,所以其返回类型是 Any
fun publicFoo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // 没问题
val x2 = publicFoo().x // 错误:未能解析的引用“x”
}
}
Other variables in the scope can be easily accessed in the object expression
fun countClicks(window: JComponent) {
var clickCount = 0
var enterCount = 0
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
clickCount++
}
override fun mouseEntered(e: MouseEvent) {
enterCount++
}
})
// ……
}
Object declaration
Kotlin uses the object keyword to declare an object.
In Kotlin, we can easily obtain a singleton through object declaration
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ……
}
val allDataProviders: Collection<DataProvider>
get() = // ……
}
To refer to the object, we can use its name directly
DataProviderManager.registerDataProvider(……)
Of course, you can also define a variable to get this object. When you define two different variables to get this object, you will find that you can't get two different variables. In other words, in this way, we get a singleton
var data1 = DataProviderManager
var data2 = DataProviderManager
data1.name = "test"
print("data1 name = ${data2.name}")
Instance
In the following example, both objects output the same URL address
object Site {
var url:String = ""
val name: String = "菜鸟教程"
}
fun main(args: Array<String>) {
var s1 = Site
var s2 = Site
s1.url = "www.runoob.com"
println(s1.url)
println(s2.url)
}
The output result is
www.runoob.com
www.runoob.com
Objects can have supertypes
object DefaultListener : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ……
}
override fun mouseEntered(e: MouseEvent) {
// ……
}
}
Unlike object expressions, when an object is declared inside another class, the object cannot be accessed through an instance of the external class, but can only be accessed through the class name, and the object cannot be directly accessed to the external class. Methods and variables
class Site {
var name = "菜鸟教程"
object DeskTop{
var url = "www.runoob.com"
fun showName(){
print{"desk legs $name"} // 错误,不能访问到外部类的方法和变量
}
}
}
fun main(args: Array<String>) {
var site = Site()
site.DeskTop.url // 错误,不能通过外部类的实例访问到该对象
Site.DeskTop.url // 正确
}
Companion object
The object declaration inside the class can be marked with the companion keyword, so that it is associated with the external class, and we can directly access the internal elements of the object through the external class
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
val instance = MyClass.create() // 访问到对象的内部元素
We can omit the object name of the object, and then use Companion to replace the object name that needs to be declared
class MyClass {
companion object {
}
}
val x = MyClass.Companion
Note: Only one internal association object can be declared in a class, that is, the keyword "companion" can only be used once.
The members of companion objects look like static members in other languages, but they are still instance members of real objects at runtime. For example, you can also implement the interface
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
Semantic differences between object expressions and object declarations
There is an important semantic difference between object expressions and object declarations:
-
Object expressions are executed immediately where they are used
-
The object declaration is lazily initialized when it is accessed for the first time
-
The initialization of the companion object matches the semantics of the Java static initializer when the corresponding class is loaded (parsed)