Object expression

Object expressions and object declarations

Kotlin uses object expressions and object declarations to create an object of a class that has made minor changes to a class, and there is no need to declare a new subclass.

Object expression

Implement an object of an anonymous inner class through an object expression and use it in the parameters of the method:

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 object expression, you can directly get an object across the definition of the class:

fun main(args: Array<String>) {
    val site = object {
        var name: String = "Rookie tutorial"
        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, 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 to anonymous objects will not be accessible.

class C {
    // Private function, so its return type is anonymous object type
    private fun foo() = object {
        val x: String = "x"
    }

    // Public function, so its return type is Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // no problem
        val x2 = publicFoo().x  // Error: failed to resolve reference 'x' for
    }
}

You can easily access other variables in the scope in the object representation:

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 reference this object, we can directly use its name:

DataProviderManager.registerDataProvider(......)

Of course, you can also define a variable to get the object. When you define two different variables to get the object, you will find that you can't get two different variables. That is, in this way, we get a single example.

var data1 = DataProviderManager
var data2 = DataProviderManager
data1.name = "test"
print("data1 name = ${data2.name}")  

example

In the following example, both objects output the same url address:

object Site {
    var url:String = ""
    val name: String = "Rookie tutorial"
}
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 the instance of the external class, but only through the class name. Similarly, the object cannot directly access the methods and variables of the external class.

class Site {
    var name = "Rookie tutorial"
    object DeskTop{
        var url = "www.runoob.com"
        fun showName(){
            print{"desk legs $name"} // Error, unable to access methods and variables of external classes
        }
    }
}
fun main(args: Array<String>) {
    var site = Site()
    site.DeskTop.url // Error, the object cannot be accessed through an instance of an external class
    Site.DeskTop.url // correct
}

Companion Object

The object declaration inside the class can be marked with the company keyword, so 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()   // Accessing internal elements of an object

We can omit the object name of the object, and then use Companion instead of the object name 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 company can only be used once.

Make sure that the members of the companion object look like static members of other languages, but they are still instance members of the real object at run time. For example, you can also implement interfaces:

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
  • Object declarations delay initialization when first accessed
  • The initialization of the associated object matches the semantics of the Java static initializer when the corresponding class is loaded (parsed)

Added by trmbne2000 on Mon, 24 Jan 2022 20:54:07 +0200