Talking about the variables and constants of Kotlin grammar (2)

https://my.oschina.net/u/3847608/blog/1837610 

This time I talked about Kotlin's variables and constants, and I will mainly introduce the following:

  • 1. Basic definition of variables
  • 2. The difference between var and val
  • 3. Intelligent type inference
  • 4. Custom attribute accessor
  • 5. Is var is variable and val must be immutable?

1. Comparison of variable and constant usage in Kotlin and Java

  • 1. Define a variable and constant in Java
public String name = "Mikyou";//定义变量
public final int age = 18;//final定义常量
  • 2. Define a variable and constant in Kotlin
var name: String = "Mikyou"
val age: Int = 18

or

var name = "Mikyou"
val age = 18

Summary: From the above comparison, we can get:

  • 1. Kotlin defines a variable and constant more concise and flexible than Java
  • 2. Kotlin has a type inference mechanism. When a variable or constant is initialized, the type declaration can be omitted, and it will be used as the type of the variable according to the type of the initialized value.
  • 3. Kotlin declares that variables and constants must use var (variable), val (constant) keyword begins, then name, and finally type (if there is an initialized value type, it can be omitted directly)
  • 4. Compared with Java, Kotlin's default access modifier is public, and Java is default
  • 5. Java generally starts with the type and then the name, and the type cannot be omitted; this kind of operation is not possible in Kotlin. Because the type can be omitted in Kotlin, that is, the type is relatively weak, so Kotlin will put the type at the end, generally containing the initialization value will omit the subsequent type declaration.

Two, Kotlin's variable and constant usage

var name: String = "Mikyou"
var address: String?//如果这个变量没有初始化,那么需要显示声明类型并且指明类型是否可null
address = "NanJing"
val age: Int = 18

or

var name = "Mikyou"
val age = 18
  • 1. Variables and constant declarations must start with the keywords "var" and "val".
  • 2. The structure of variables and constants: (var or val) Name: (Split comma) Variable type = initialization value.
  • 3. Intelligent type conversion (the compiler prompts as smart cast). If the variable or constant contains the initial value, the type can be omitted. The compiler will analyze the type of the initialized value as the variable and constant type by default.
  • 4. If the variable is not initialized, the declared type needs to be displayed and whether the type is nullable or not needs to be specified.

Three, Kotlin's custom attribute accessor

Attributes are the first-class feature in Kotlin. It is used to replace fields and setter and getter methods in Java with an attribute. The set and get accessors in Kotlin are equivalent to the setter and getter methods in Java. A new feature of Kotlin is that you can define accessors for properties in a class, including setter and getter accessors. This feature is very suitable for a new attribute that needs to be calculated through multiple attribute logic. Then the process operation of logical calculation does not need to open a method like Java to achieve. You can perform logical operations directly in the attribute accessor.

  • 1. Custom get attribute accessor

Implemented in Java:

public class Rectangle {

    private float width;
    private float height;

    public Rectangle(float width, float height) {
        this.width = width;
        this.height = height;
    }

    public boolean isSquare() {//在java中实现一个方法进行相关的逻辑计算
        return width == height;
    }

}

Implemented in Kotlin:

class Rectangle(width: Float, height: Float) {
    val isSquare: Boolean//在Kotlin中只需要一个属性就能解决,重新定义了isSquare的getter属性访问器,访问器中可以写入具体逻辑代码。
        get() {
            return width == height
        }
}
  • 2. Custom set attribute accessor

Implement a setter method in a custom View in Android in Java.

public class RoundImageView extends ImageView {
        ...
    
    public void setBorderColor(int color) {
        mColor = color;
        invalidate();
    }
        ...
}

Implement the set attribute accessor in a custom View in Android in Kotlin.

class RoundImageView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defAttrStyle: Int = 0)
    : ImageView(context, attributeSet, defAttrStyle) {

    var mBorderColor: Int
        set(value) {//自定义set属性访问器
            field = value
            invalidate()
        }
}

Fourth, the difference between var and val in Kotlin

  • 1, var (from variable) variable reference . And the value of the variable modified by it can be changed, with read and write permissions, which is equivalent to non-final variables in Java.
  • 2. Val (from value) is an immutable reference . And the value of the variable modified by it is generally initialized and cannot be re-thrown in the later stage, otherwise it will throw a compilation exception ( this sentence is to be discussed, please see the discussion of immutable and readable val in Kotlin ), which is equivalent Final modified constants in Java.
  • 3. In the Kotlin development process, use the val keyword to declare all Kotlin variables as much as possible. Only use var in some special cases. We all know that functions in Kotlin are first-class citizens, and a lot of functional programming content is added. The use of immutable referenced variables makes it closer to the style of functional programming.
  • 4. It should be noted that the val reference itself is immutable, but the object it points to may be mutable ( for discussion and verification of this issue, please refer to the discussion of immutable and readable val in Kotlin ).
  • 5. The var keyword allows to change its value, but its type cannot be changed.

5. Discussion on immutability and readability of val in Kotlin

Since Kotlin is a new language, we often habitually remember some so-called theorems in the process of learning, without really going into the details of why it is so. For example, taking today's topic, I believe many people think (including myself at the beginning) that the variables modified by var are mutable, while the variables modified by val are immutable. Then, after learning Kotlin's custom attribute accessor, you will feel that there is a problem. Then I went to look at some foreign blogs. Although there are descriptions, after reading it, what makes me even more confused is that the value of the variable modified by val can be changed and read, and the underlying reference is also changed. The first sentence is indeed understandable, but the latter sentence is still reserved. So I started writing demo authentication. Quoting the original sentence of a foreign blog "But can we say that val guarantees that underlying reference to the object is immutable? No..." foreign blog source address

  • 1. The assumption that val is immutable and readable

Hypothesis 1: The variable modified by val in Kotlin cannot be said to be immutable, it can only be said that the permission of val modified variable is readable.

Hypothesis 2: The reference to the variable modified by val in Koltin is immutable, but the object pointed to is variable.

  • 2. Argument that val is immutable and readable

Argument Hypothesis 1: In the development process of Kotlin, we generally use val-modified variables that cannot be assigned again, otherwise a compile-time exception will be thrown. But the fact that it cannot be assigned again does not mean it is immutable. Because Kotlin is different from Java in the feature of custom attribute accessors. This feature seems to contradict the immutability of the variable modified by val. This problem does not exist in Java. If final modified variables are used, there is no so-called custom accessor concept.

fun main(args: Array<String>) {
    val name = "Hello Kotlin"
    name = "Hello Java"
}

print error:

Error:(8, 5) Kotlin: Val cannot be reassigned

Define get attribute accessor example

class RandomNum {
    val num: Int
        get() = Random().nextInt()
}

fun main(args: Array<String>) {
    println("the num is ${RandomNum().num}")
}

print result:

the num is -1411951962
the num is -1719429461

Summary: The above example can show that Hypothesis One is true. The variable modified by val in Kotlin cannot be said to be immutable, but only has readable permissions.

Argument Hypothesis 2: From Argument 1, we know that the variable modified by Kotlin's val is mutable, so is its underlying reference mutable? A foreign blog says that citations are variable. Is this true? Through an example to illustrate.

User class:

package com.mikyou.kotlin.valtest
open class User() {
    var name: String? = "test"
    var age: Int = 18
    var career: String? = "Student"
}

Student class:

class Student() : User()

Teacher category:

class Teacher() : User()

Customer interface:

interface Customer {
    val user: User//注意: 这里是个val修饰的User实例引用
}

VipCustomer implementation class:

class VipCustomer : Customer {
    override val user: User
        get() {
//            return Student().apply {
//                name = "mikyou"
//                age = 18
//                career = "HighStudent"
//            }
            return Teacher().apply {
                //看到这里很多人肯定认为,底层引用也会发生改变,毕竟Student, Teacher是不同的对象了。但是事实是这样的吗?
                name = "youkmi"
                age = 28
                career = "HighTeacher"
            }
        }
}

test:

fun main(args: Array<String>) = VipCustomer().user.run {
    println("my name is $name, I'm $age years old, my career is $career, my unique hash code is ${hashCode()} ")
}

print result:

my name is mikyou, I'm 18 years old, my career is HighStudent, my unique hash code is 666988784 
	
//切换到Teacher
my name is youkmi, I'm 28 years old, my career is HighTeacher, my unique hash code is 666988784

Summary: From the above example, it can be shown that hypothesis two is true. Two different object hashCodes indicate that the user's reference address is unchanged, and the object that the reference points to can be changed.

This is the end of the basic grammar of Kotlin entry. The next article will continue to dive into Kotlin related content

Guess you like

Origin blog.csdn.net/az44yao/article/details/112917698