Kotlin Learning Series: Use Cases of object keywords, kotlinobject

Source: Internet
Author: User

Kotlin Learning Series: Use Cases of object keywords, kotlinobject

Object is an important keyword in Kotlin and is not in Java. Objects can be used in the following scenarios:

Object Declaration(Object Declaration) Companion object(Companion Object) Object expression(Object Expression)

The following describes the meanings, usage, and notes of these keywords, so that you can fully understand the usage of the object keywords after reading this article.

1. Object Declaration)

1) syntax meaning: Combine the class declaration and the singleton object defining the class (that is, the singleton mode is implemented through the object)
2) basic example

object RepositoryManager{    fun method(){        println("I'm in object declaration")    }}
Replace the class keyword with the object keyword to declare a class and an object. As long as you write so much code, this class is already a singleton.

3) Use

A. In Kotlin:

fun main(args: Array
 
  ) {    RepositoryManager.method()}
 

The method defined in this method is called in Java just like calling a static method (there is no static method in kotlin), but it is actually a singleton using the RepositoryManager class.ObjectCall the instance method. If you still cannot understand this, you can take a look at the instructions for using it in Java.

B. in Java:

public class JavaTest {    public static void main(String[] args) {        RepositoryManager.INSTANCE.method();    }}

In other words, the object declaration class is eventually compiled into: A class has a static member to hold its reference to itself, and the static member name is INSTANCE, of course, this INSTANCE is a Singleton, so it can be used here. If you use Java code to declare this RepositoryManager, you can use the following code:

class RepositoryManager{    private RepositoryManager(){}    public static final RepositoryManager INSTANCE = new RepositoryManager();}

4) Notes:

Although like the declaration of a common class, it can contain attributes, methods, initialization code blocks, and inherit other classes or implement an interface, however, it cannot contain Constructors (including the master constructor and sub-constructor). It can also be defined inside a class:
 class ObjectOuter {     object Inner{         fun method(){             println("I'm in inner class")         }     } } fun main(args: Array
 
  ) {     ObjectOuter.Inner.method() }
 

2. Companion object)

Before describing the companion object, we must first make it clear that there is no static keyword in Kotlin, that is, there is no static method or static member. In kotlin, If you want to express this concept, replace it with the package-level function and the companion object we mentioned here. We will talk about the differences between them later.

1) Syntax:

Class A {companion object name (can be omitted) {// define method and field here }}

2) basic example:

 
class ObjectTest {    companion object MyObjec{        val a = 20        fun method() {            println("I'm in companion object")        }    }}

3) use:

A. In Kotlin:

 
Fun main (args: Array
 
  
) {// Method 1 ObjectTest. myObject. method () println (ObjectTest. myObject. a) // method 2 (recommended) ObjectTest. method () println (ObjectTest. a )}
 

Note: When defining (if the associated object name is omitted during definition, the compiler will provide it with the default name Companion) and calling, the associated object name can be omitted. In method 2, pay attention to the calling form through the class name. method Name (). When an object of the ObjectTest class is not generated, the attributes and methods defined in its internal companion object are called, is it similar to the concept of static methods in Java.

4) view the essence through Phenomena

Through the javap command, let's look at the generated bytecode:

Note that in the red box, the MyObject member variable type is connected using $. This means that when defining the companion object, we actually treat it as a static internal class, and the target class will hold a reference of this internal class. The final method called is actually the instance method defined in this static internal class, you can also use the ObjectTest $ MyObject class javap.

5) I still remember the previous issues: they can also be used to replace the static concept in Java. What is the difference between the methods defined in the companion object and the package-level functions?

First, decompile a kt file (or a class) containing the package-level functions ):

As you can see, a file named ObjectTest2.kt actually generates a class named ObjectTest2Kt, and the top-level function (package-level function) defined in this kt File) it exists as a static method of this class.

Now you can answer the remaining questions: the difference between the static methods in the class and the instance methods in the internal class, because the methods in the member's internal class can access the methods and Members defined in the external, even if they are private, static methods cannot do this. If you think the text description is not intuitive enough, let's look at the figure below:

6) @ JvmStatic annotation: add this annotation to the method defined earlier, re-build the project, and decompile the ObjectTest and ObjectTest $ MyObject classes to see what changes will happen.

For this static internal class, the structure of the class added with or without @ JvmStatic annotation is unchanged. But for the target class, it is obvious that there is a static method, so that we can not easily understand the role of @ JvmStatic annotation: The instance methods and attributes defined in the companion object class, added to the target class and exists in static form.

7) for companion objects, add one more point: Only one companion object of a class can exist. It is easy to think about it. The name of the companion object can be omitted. If multiple associated objects are allowed, the same functions are defined in multiple associated objects. Which method of companion object is used for calling? It will produce ambiguity, so it is not difficult to understand this syntax.

3. Object Expression)

1) Java anonymous internal class review:

Before learning object expressions, let's review the anonymous internal classes in Java.

Interface Contents {void absMethod ();} public class Hello {public Contents contents () {return new Contents () {@ Override public void absMethod () {System. out. println ("method invoked... ") ;}};} public static void main (String [] args) {Hello hello = new Hello (); hello. contents (). absMethod (); // print method invoked ...}}

The contents () method returns an anonymous internal class object, which implements the Contents interface. These codes are very familiar. Two limitations are raised:

A. If some attributes and methods are added to the anonymous internal class, they cannot be called outside the world.

return new Contents() {            private int i = 1;            public int value() {                return i;            }            @Override            public void absMethod() {                System.out.println("method invoked...");            }        }; public static void main(String[] args) {        Hello hello = new Hello();        hello.contents().absMethod();        hello.value();  //Cannot resolve method 'value()'    }

The compiler reports an error when you want to use this value method. It can also be understood as a multi-state knowledge. the reference of the parent type cannot be aware of the existence of the subclass addition method.

B. An anonymous internal class must implement an interface or inherit one class, and can only be one. in mathematical terms, it is "one and only one"

2) Syntax:

Object [: interface 1, interface 2, type 1, type 2] {}// can be omitted in brackets

3) Example:

A. Implement an interface or Class

interface AA {    fun a()}fun main(args: Array
 
  ) {    val aa = object : AA {        override fun a() {            println("a invoked")        }    }    aa.a()}
 

B. Do not implement any interfaces and classes, and add methods to anonymous internal classes.

Fun main (args: Array
 
  
) {Val obj = object {fun a () {println ("a invoked")} obj. a () // print: a invoked}
 

From this example, we can see that the second limitation of the Java anonymous internal class mentioned above does not exist in Kotlin, and the newly added method can also be called.

C. implement multiple interfaces and Classes

fun main(args: Array
 
  ) {    val cc = object : AA, BB() {        override fun a() {        }        override fun b() {        }    }    cc.a()    cc.b()}
 

From this example, we can see that the first limitation of the Java anonymous internal class mentioned above does not exist in kotlin.

4) usage notes:

This is a passage in the official Kotlin document: only when an anonymous object is defined as a local variable or a private member variable can its actual type be reflected. If you use an anonymous object as the return value or public attribute of the public function, you can only regard it as its parent class. Of course, if you do not specify Any type, you can treat it as Any. In this case, the attributes and methods you add to an anonymous object cannot be accessed.

Let's take an example to help you understand:

Class MyTest {private val foo = object {fun method () {println ("private")} val foo2 = object {fun method () {println ("public ")}} fun m () = object {fun method () {println ("method")} fun invoke () {val local = object {fun method () {println ("local")} local. method () // compiled through foo. method () // compiled through foo2.method () // The compilation fails to pass m (). method () // compilation and translation Failed }}

5) questions about accessing the local variables defined under the same role in an anonymous object:

In Java, If you access a locally defined external variable in an anonymous internal class, the local variable must be modified using the final keyword. In Kotlin, this restriction is absent. Let's look at the following example:

Var a = 1 val obj = object {fun method () {a ++} obj. method () println (a) // print 2

In Java, actually, the used in the method is actually a copy of the local variable a, rather than itself. In the end, Kotlin also needs to be compiled into bytecode for JVM to execute, so in essence it will not violate this point. So how does it deal with it?

When the local variable you access is val, it is also very similar to Java, with a copy; and when you are a variable (var, its value is stored in the instance Member of the Ref class. The Ref variable is final, and its member variables can be changed. After decompiling, you can see the figure of Ref.

Here is some interesting code to post to you:

fun tryToCountButtonClicks(button: Button): Int{var clicks = 0button.setOnClickListener{    clicks++}return clicks}
A button is a Button. This Code is intended to count the number of times a button is clicked. However, the return value of this function is always 0, even if you click it multiple times. Because the modification to the local variable clicks is asynchronous, And the return value of this function is determined during execution, that is, your value has not been modified, and the function has already returned. To count the number of clicks, you can define clicks as a member variable of the class.

4. Compare the initialization time of object declaration, Companion object, and object expression:

A. object declaration: initialization is performed only when the object is accessed for the first time. It is a type of lazy initialization.

B. Companion object: It is initialized only after its corresponding class is loaded, similar to the static code block in Java.

C. object expression: Initialize the object immediately after it is executed.

So far, we have finished introducing the use of the object keyword in Kotlin. I hope you will get some benefits ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.