Constructor in Kotlin, accompanying object explanation

There are some things in Kotlin that seem pretty simple, like we can use them without a problem, right? But that doesn’t mean we understand that these are just points, we just know how to use them, and to understand them, we need to understand their nature. Today we are going to introduce some things from Kotlin that we seem to understand, but don’t quite understand.

Kotlin Class that we missed

First up, class, let’s look at a Java class.

 class MyJavaClass {
     static String staticMember; // Static variables
     private String word;
     public MyJavaClass(a){} // No argument constructor
     public MyJavaClass(String word){ // A constructor for one argument
         this.word = word;
     }
 ​
     public MyJavaClass(String word,String staticMemberParam){// A two-argument constructor
         this.word = word;
         staticMember = staticMemberParam; // Static variables can be used in constructors
     }
     
     public void sayWord(a){// Ordinary member methods
         System.out.println("hello i am java class i can say "+word);
     }
 ​
     public String getWord(a) { / / get methods
         return word;
     }
 ​
     public void setWord(String word) {/ / set methods
         this.word = word;
     }
 ​
     static void printlnStatic(a){// Static method
         System.out.println("hello "+staticMember); }}Copy the code

If you use the Java to Kotlin tool to convert, the result will be wrong. Next, let’s go through what we know today step by step.

The first is to define a member word

var word: String? = null fun getWord(): String? Return word} fun setWord(word: String?) {// error this.word = word}Copy the code

If we define a member variable in Kotlin as we do in Java and give it setter getter methods, the compiler will tell us that something is wrong. What???

Is it so simple that it’s written wrong? What lJ language? I’m done with it. (Fake, pick up your textbook).

The following declarations have The same JVM signature: The following declarations have The same JVM signature as another method. That said, there is another method that is also fun getWord(). In kotlin, getter and setter methods are implemented by default when member variables are declared. So only one variable needs to be declared. As follows:

 var word: String? = null
Copy the code

Isn’t that easy?

Principal constructor

In Kotlin, using constructors requires the keyword constructor, and constructors distinguish between primary and secondary constructors

The primary constructor is part of the class header: it follows the class name (along with optional type arguments), and the primary constructor cannot contain any code.

 // This is a simple main constructor(). Note that it does not have a function body, so what use is it? Don't worry, we'll get to that later
 class MyKotlinClass constructor() {
     var word: String? = null
 }
Copy the code
subconstructor

Classes can also declare subconstructors prefixed by constructor:

If a class has a primary constructor, each subconstructor needs to delegate to the primary constructor, either directly or indirectly through another subconstructor. Delegate to another constructor of the same class using the this keyword as follows:

class MyKotlinClass constructor() { var word: String? = null constructor(word: String?) :this() { this.word = word } }Copy the code

Going back to the above question, the main constructor doesn’t have a function body, so what’s the use of it? In Kotlin, there is the declaration of member variables and the initialization of the init{} code block. This part will actually be the body of the main constructor. What does it mean? Let’s use an example to illustrate:

 class MyKotlinClass constructor(word:String?) {
     var mWord: String? = word
     init{
         println(mWord)
     }
     constructor(word: String? ,word2:String):this(word) {
         println(word2)
     }
 }
Copy the code

If you look at the example above, the body of the main constructor corresponds to the following part

 var mWord: String? = word
 init{
     println(mWord)
 }
Copy the code

The delegate to the primary constructor is the first statement of the secondary constructor, so all code in the initializer block and property initializer is executed before the secondary constructor body. Even if the class does not have a primary constructor, this delegate occurs implicitly and the initialization block is still executed. This sentence is useful for determining the order in which some blocks of code are executed. The argument in the main constructor can only be used in the init block or when declaring a member variable, not in any other method body. If we want it to be used in any other method body, we should prefix it with the val or var keyword, which is equivalent to declaring a member variable. The following

 class MyKotlinClass constructor(var word:String?) {
     init{
         println(word)
     }
     constructor(word: String? ,word2:String):this(word) {
         println(word2)
     }
     fun test(a){
         println(word)
     }
 }
Copy the code

That is the difference between a primary constructor and a secondary constructor. If there are multiple constructors, how do you choose which one to use as the primary constructor? Choose the most used constructor as the primary constructor.

Associated object

Going back to the example above, if you want to declare static variables in Kotlin with the static keyword, you cannot do so because kotlin does not have the static keyword. So how do you declare it if you need to? That’s where the companion comes in.

In Kotlin, it is possible to create associated objects using the Complain Object. For example, if I wanted to declare a staticMember variable, I would declare it like this:

 companion object{
     var staticMember: String? = null
 }
Copy the code

Decompiled into Java code, it looks like this

 public final class MyKotlinClass {
    @Nullable
    private static String staticMember;
    @NotNull
    public static final MyKotlinClass.Companion Companion = new MyKotlinClass.Companion((DefaultConstructorMarker)null);
    public static final class Companion {
       @Nullable
       public final String getStaticMember(a) {
          return MyKotlinClass.staticMember;
       }
 ​
       public final void setStaticMember(@Nullable String var1) {
          MyKotlinClass.staticMember = var1;
       }
 ​
       private Companion(a) {}// $FF: synthetic method
       public Companion(DefaultConstructorMarker $constructor_marker) {
          this(a); }}}Copy the code

The static member variable of MyKotlinClass is the static member variable of MyKotlinClass. This way, calling static member variables in Java is not the same as calling them in Kotlin.

 / / in the kotlin calls
 MyKotlinClass.staticMember
Copy the code
 / / call in Java
 MyKotlinClass.Companion.getStaticMember()
Copy the code

This is the basic content, mainly want to tell you some do not know the knowledge, we can decompile into Java code to see.