preface

When I started working, the company boss suggested learning from Kotlin, which would speed up development, prevent null Pointers, and a whole bunch of good things to use. But, at first, I didn’t believe it. What is Kotlin? I heard that the return type of a function is always after the method name. However, in view of the big guy recommendation, it seems that understanding is necessary, so ,,,,,,,,, Kotlin really fragrant! With all that nonsense, let’s get down to business. Here’s the text

The body of the

As you know, in Java, there is a special treatment for strings. Strings can be added to any object, even if it is null.

But when I learned Kotlin, I found that the “+ “method of automatically converting objects to strings was not enjoyable (although Kotlin has a better String template function, which makes writing code much more enjoyable, but I just like the “+”, a good programmer), not only that strings cannot be added, Different types of numbers can no longer be added together, which makes a Java programmer very uncomfortable (maybe it’s just me, haha), ORIGINALLY I was going to be a kotlin fan, but in line with the principle of finding problems, I continued to study Kotlin, and then kotlin smell good again!!

When I learned about extension functions and operator functions on kotlin’s website, I finally understood why Kotlin smells so good. How can an object be concatenated with a String using the ‘+’ operator? The code is as follows:

operator fun String.plus(i:Int)=this+i.toString()
fun main(a) {
    val i=5
    val re="2222"+i
    println(re)
}
Copy the code

In this case, we can happily use ‘+’ for Int (we’ll see what the plus function does later), but note that I can only be placed to the left of +. If I is placed to the right of +, an error will be reported, as shown in the figure below

Extension function
The operator
Killer feature

The kotlin operator is overloaded

What is operator overloading?

Kotlin allows us to provide an implementation of a predefined set of operators for our types. These operators have fixed symbolic representation (such as + or *) and fixed precedence. To implement such operators, we provide a member function or extension function with a fixed name for the corresponding type (that is, the type to the left of the binary operator and the parameter type of the unary operator). Functions that overload an operator need to be marked with an operator modifier. In addition, we describe conventions that regulate operator overloading for different operators. So that’s the official introduction to operators. Unary operators refer to a++,a, which only operate on one expression. Binary operators refer to a+b,a- b,a *b,a /b, which combine two expressions into a slightly more complex expression. In Kotlin, each of these operators corresponds to a function that is modified by the operator.

Basic operator enumeration

The unary operators are as follows:

expression function
+a a.unaryPlus()
-a a.unaryMinus()
! a a.not()
a++ a.inc() +
a– a.dec() +

Binary operators (only the basic arithmetic operators are listed here, others such as in,== are listed on the official website) :

expression function
a + b a.plus(b)
a – b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b A. em(b), A.m.od (b) (deprecated)
a.. b a.rangeTo(b)

The sample

As we can see from the above, operators correspond to functions. In this way, we only need to define the corresponding method of a class, and can add. Here, let’s take the Money category as an example.

class Money(val value: Int) {
    operator fun plus(money: Money): Money {// This is the + sign
        val sum = this.value + money.value
        return Money(sum);
    }

    operator fun plus(money: Int): Money {// This is the + sign
        val sum = this.value + money
        returnMoney(sum); }}fun main(a){
	val money=Moeny(5)
	val num=5
	val balance=money+num
	println("Moeny.$balance")}Copy the code

The plus function of the Money class implements the + operator, so let’s see how kotlin implements the + operator in Java. How to see the Java code for Kotlin (click to enter).

The example corresponds to Java source analysis

public final class Money {
   private final int value;

   @NotNull
   public final Money plus(@NotNull Money money) {
      Intrinsics.checkParameterIsNotNull(money, "money");
      int sum = this.value + money.value;
      return new Money(sum);
   }

   @NotNull
   public final Money plus(int money) {
      int sum = this.value + money;
      return new Money(sum);
   }

   public final int getValue() {
      return this.value;
   }

   public Money(int value) {
      this.value = value; }}public final class TempKt {
   private static final StringBuilder build(@NotNull StringBuilder $this$build, Function1 block) {
      block.invoke($this$build);
      return $this$build;
   }

   public static final void main() {
      Money money = new Money(5);
      int num = 5;
      Money balance = money.plus(num);
      String var3 = "The moeny." + balance;
      boolean var4 = false;
      System.out.println(var3);
   }

   // $FF: synthetic method
   publicstatic void main(String[] var0) { main(); }}Copy the code

From the code we can see that the Java equivalent of main is a Java main method in class TempKt, which is called in the entry method main. There’s nothing to say about the Money class. The methods are basically the same as the ones in Kotlin. The focus is on koltin’s val balance= Money +num line. Money balance = money.plus(num); Obviously, the + has been replaced by the corresponding method. But these are just two expressions added together, so let’s do another one and see what happens.

Money money = new Money(5);
int num1 = 5;
int num2 = 10;
Money balance = money.plus(num1).plus(num2);
Copy the code

Corresponding Java code

Money balance = money.plus(num1).plus(num2);
Copy the code

The plus keeps getting replaced by the plus.

Operator overload summary

With this code, we know about operator overloading in Kotlin and the corresponding Java code conversion. Int + String = Int + String = Int + String = Int + String = Int + String = Int + String Because we only implemented plus on one side, we implemented an overload of the left-add operator, which means String on the left and Int on the right. We add the left operator to make it ok, as follows:

package com.example.jetpacklearn.kotlinlearn
operator fun Int.plus(s:String)=this.toString()+s
operator fun String.plus(i:Int)=this+i.toString()
fun main(a) {
    val i=5
    val re=i+"2222"
    println(re)
}
Copy the code

This is done by adding an extension function to the Int class that is overloaded by the operator.

However, as you might have noticed, the Money operator overloads define methods in the Money class. This is obviously different from the String operator overloads we implemented at the beginning. So, another feature of Kotlin is the extension function (official transporter). Let’s move on to the extension function (official portal).

The Kotlin extension function

What is kotlin’s extension function?

Kotlin can extend a class to new features without inheriting the class or using design patterns like decorators. This is done through special declarations called extensions. For example, you can write a new function for a class from a third-party library that you cannot modify. This new function can be called as a normal method, just like the original one. This mechanism is called an extension function. In addition, there are extended properties, which allow you to add new properties to an existing class.

Extension functions make it easier for developers to use a method, and the method is bound to a class, making it more intuitive to use. You can see who the method is for. There are extended attributes, this article does not introduce, we go to the official website to see it, the extended portal here.

The sample

In this case, we will use the Money class as an example. The Money class stores the value of Money, but the ratio of Money is different, so we need to add a currency calculation function, such as the value of the DOLLAR for RMB. But we don’t want to change the structure of the Money class, so we can use the extension function to add an extension function called convertToDollar to the Moeny class

class Money(val value: Double.val type:String){
/ / to omit
}
fun Money.convertToDollar(a): Money {
    when(this.type){
        "rmb"- > {return Money(this.value*6.5."dollar")}"dollar"- > {return Money(this.value,this.type)}
        else->
            throw Exception("Unknown type")}}fun main(a){
    val rmb=Money(5.0)
    println("moeny   value:${rmb.value}  type:${rmb.type}")
    val dollar=rmb.convertToDollar()
    println("moeny   value:${dollar.value}  type:${dollar.type}")}Copy the code
#The resultsMoeny value:5.0 Type: RMB Moeny value:0.7692307692307693 Type :dollarCopy the code

Sample generated Java code

In our example, we have the extension function written and running, so what does the Java code for this kotlin code look like? The decompiled Java code looks like this:

public final class TestKt {
   private static final StringBuilder build(@NotNull StringBuilder $this$build, Function1 block) {
      block.invoke($this$build);
      return $this$build;
   }

   @NotNull
   public static final Money convertToDollar(@NotNull Money $this$convertToDollar) {
      Intrinsics.checkParameterIsNotNull($this$convertToDollar, "$this$convertToDollar");
      String var1 = $this$convertToDollar.getType();
      switch(var1.hashCode()) {
      case -1326217028:
         if (var1.equals("dollar")) {
            return new Money($this$convertToDollar.getValue(), $this$convertToDollar.getType());
         }
         break;
      case 113031:
         if (var1.equals("rmb")) {
            return new Money($this$convertToDollar.getValue() / 6.5D, "dollar"); }}throw (Throwable)(new Exception("Unknown type"));
   }

   public static final void main(a) {
      Money rmb = new Money(5.0D, (String)null.2, (DefaultConstructorMarker)null);
      String var1 = "moeny value:" + rmb.getValue() + " type:" + rmb.getType();
      boolean var2 = false;
      System.out.println(var1);
      Money dollar = convertToDollar(rmb);
      String var5 = "moeny value:" + dollar.getValue() + " type:" + dollar.getType();
      boolean var3 = false;
      System.out.println(var5);
   }

   // $FF: synthetic method
   public static void main(String[] var0) { main(); }}Copy the code

From the above code, we can see that the Java method corresponding to the extension function does not appear in the Money class. It appears in the TestKt class, which is the same class as the Kotlin main function. $this$convertToDollar value, type ($this$convertToDollar value, type) This is a common variable name that starts with $. The “this” character is not really the “this” character inside the object, it is a common character, and it is more of a way of naming flowers. We also see how the when keyword in Kotlin translates to the Switch in Java. All right, so that’s it, that’s the extension function. Again going back to our beginning, the implementation of the String ‘+’ operator, found so simple, haha.

Kotlin generic

But !!!!!!!!!!!!!!!! You will notice that this only implements the ‘+’ operation on Int and String. Would we have to rewrite every class to implement the ‘+’ operation on String ???? That’s too tired !!!!!!!!!!! Kotlin supports generics, just like Java. I’m sure you’re familiar with Java generics. Kotlin’s generics are not much different than Java’s. Let’s use generics to make the Java string addition operation really ported to Kotlin!! The code is as follows:

operator fun <T> T.plus(s: String) = this.toString() + s
operator fun String.plus(t:Any)= this+t.toString()
Copy the code

summary

This article from the String ‘+’ operator implementation, the extension of kotlin operator overload, function extension and other knowledge, just started to write the article, if there is a problem, also please criticize correct!

Original statement

Author: Chen Haoliang

Links:

  1. CSDN Kotlin goes from implementing the String ‘+’ operation to understanding operator overloading and function extension
  2. Kotlin’s brief goes from implementing the String ‘+’ operation to understanding operator overloading and function extension