Kotlin learning: Kotlin object expressions and object declarations

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)

Guess you like

Origin blog.csdn.net/PrisonJoker/article/details/113798125