Object declarations (Object declarations)

The singleton pattern is easily implemented using the Object declaration

object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
    // ...
}
val allDataProviders: Collection<DataProvider>
    get() = // ...
}
Copy the code

So that’s an object declaration, just like declaring a variable. Use as follows:

DataProviderManager.registerDataProvider(...)
Copy the code

This completes the construction of a convenient singleton pattern.

An object can have a parent class:

object DefaultListener : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { // ... } override fun mouseEntered(e: MouseEvent) { // ... }}Copy the code

Note: Object cannot be used as an inner class

companion object

When you use Object inside a class, its properties become a static part of the class, requiring the use of Companion Object

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}
Copy the code

Use as follows:

val instance = MyClass.create()
Copy the code

This is clearly a static method call. (Kotlin does not use the static keyword like Java.)

Now that we have static methods, how do we implement static properties?

The Companion Object name can be omitted, and the desired static properties and methods can be inserted. It is important to note that a static inner class (that is, a class declared directly within a class) cannot access the ordinary members of its outer class. What then? Members of the companion Object that access its external class are OK. For example:

class NotificationModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { companion object { private val TAG = "NotificationModule" private var mCachedBundle: Bundle? Private fun getName() {}} Override fun getName(): String = "notification" class Receiver: BroadcastReceiver() { override fun onReceive(context: Context? , intent: Intent?) { mCachedBundle = intent? .extras Log.d(TAG, "onReceive: $mCachedBundle") when (intent? .action) { JPushInterface.ACTION_MESSAGE_RECEIVED -> { try { val message = Intent.getstringextra (JPushInterface.EXTRA_MESSAGE) log. d(intent.getStringExtra(JPushInterface.EXTRA_MESSAGE))  " + message) mEvent = RECEIVE_CUSTOM_MESSAGE if (mRAC ! = null) { sendEvent() } } (e: Exception) { e.printStackTrace() } } } } } } }Copy the code

Object Expressions

Instantiate anonymous classes using the Object representation

In Java, anonymous classes are often used when you need to implement an interface and override its methods immediately, for example:

builder.setNegativeButton(buttons.btnCancel.title, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { // ... }});Copy the code

Kotlin would look like this:

builder.setNegativeButton(buttons.btnCancel.title, object : DialogInterface.OnClickListener() {
    override fun onClick(dialogInterface: DialogInterface, I: Int) { // ...}
}
Copy the code

just object

Sometimes you just need an object (without inheriting a class or implementing an interface)

fun foo() {
    val adHoc = object {
        var x: Int = 0
        var y: Int = 0
    }
    print(adHoc.x + adHoc.y)
}
Copy the code

This is similar to the flexible definition of object in JS.

Other precautions for use

  • Anonymous class as method return value

    Anonymous classes are usually only declared as local or private, but if they are public and not inherited, they may be returned as Any. See example:
class C {
    // Private function, so the return type is the anonymous object type
    private fun foo() = object {
        val x: String = "x"
    }
    // Public function, so the return type is Any
    fun publicFoo() = object {
        val x: String = "x"
    }
    fun bar() {
        val x1 = foo().x // Works
        val x2 = publicFoo().x // ERROR: Unresolved reference 'x'
    }
}
Copy the code
  • Access to external variables does not need to be strictly final as in Java
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++
        }
    })
// ...
}
Copy the code

The difference between object Declaration and Expressions

  • Object Expressions take effect immediately, whereas object Declarations are lazily loaded and only take effect when used
  • The instantiation of a Companion Object is dependent on the loading of its class