Kotlin Learning - Classes and Objects

class definition

Define a Personclass using Java, the code is as follows:

public class Person {
    
    
    private final String name;
    private final int age;

    public Person() {
    
           
    }

    ...
}

Use Kotlin to define this class

class Person {
    
    
    var name = ""
    var age = 0
    fun printInfo() {
    
    
        println("$name's age is $age")
    }
}

New object code:

fun main() {
    
    
   val person = Person()
   person.name = "Kotlin"
   person.age = 20
   person.printInfo()
}

//输出
Kotlin's age is 20

Attribute field, setter, getter

For each attribute defined in the class, Kotlin will generate one field, one getter, and one setter(read-only attributes have no settermethods), fieldwhich are used to store attribute data and cannot be directly defined field. Kotlin will encapsulate field, protect the data inside, and only expose getterand setteruse it.

Kotlin will provide default getterand methods, and methods can be re - setterdefined when needed . code show as below:gettersetter

class Person {
    
    
    //属性必须赋值除非是可空类型
    var nickName: String? = null
    var age = 0
    
    var name = ""
        set(value) {
    
            	
        	field = value.trim()
        }       
        get() = field.capitalize()
}

For the null judgment of nullable attributes, use

class Person {
    
    
	//属性必须赋值除非是可空类型
	var nickName: String? = null
    var age = 0
    
    var name = ""
        set(value) {
    
    
        	field = value.trim()
        }
        get() = field.capitalize()


    //如果一个函数即可变又可为空,可以在使用前使用also或者let进行判空处理
    fun printHello() {
    
    
   		nickName?.also {
    
    
            println("also - hello $it")
        }
        nickName?.let {
    
    
            print("let - hello $it")
        }
    }
}

For the use of standard library functions, you can look at Kotlin Learning - the standard functions let, with, run, apply, and also in Kotlin , and see the usage code:

fun main() {
    
    
	var p = Person()
    p.name = "Lucky"
    println(p.name)
    p.name = " tom"
    println(p.name)
	p.nickName = "kk"
    p.printHello()
}
//运行结果
Lucky
Tom
also - hello kk
let - hello kk

class inheritance

Decompile the Kotlin code above

public final class Person {
    
    
   @NotNull
   private final String name;
   ...
}

There is a modifier before the Person class final, that is, it cannot be inherited silently, and there are publicmodifiers, Kotlin's default access modifier is public.

If we declare a new class that wants to inherit Person, we need to use openkeywords. Just prefix the Person class with open:

open class Person {
    
    
    var name = ""
    var age = 0
    fun printInfo() {
    
    
        println("$name's age is $age")
    }
}

Then decompile:

public class Person {
    
    
   @NotNull
   private final String name;
   ...
}

finalThe modifier is gone, create a new Student class to inherit Person, the code is as follows:

class Student : Person(){
    
    
    ...
}

class structure

1. Main structure: write directly after the class, which is a bit like the input parameter of a function. For example, the Person class defined above is modified as follows.

open class Person constructor(_name: String, val age: Int) {
    
    
    val name: String
	
	init{
    
    
		this.name = _name.capitalize()
	}
	
    fun printInfo() {
    
    
        println("$name 's age is $age")
    }
}

In the above definition, the keyword constructorindicates the declaration of the beginning constructor. If the main constructor has no access modifier or annotation , the keyword can be removed.

initIntroduce an initialization statement block that is executed when the class is created.

A temporary variable can be defined in the constructor, and then assign values ​​to attributes, for example: as a temporary variable, internally assign values _name​​​​to member attributes . nameand a meaning in Java this.name = _name. Properties can also be defined directly in the constructor, for example: val age: Int. Here is constructorthe code after removing the keywords:

open class Person (_name: String, val age: Int) {
    
    
    val name: String
	
	init{
    
    
		this.name = _name.capitalize()
	}
	
    fun printInfo() {
    
    
        println("$name 's age is $age")
    }
}

Because the constructor of Person has been modified, Student reports an error at this time, because the Person no-argument construction was used before, and we have modified the Person construction above, so there is no no-argument construction. Modify the code as follows:

class Student(name: String,  age: Int, val nickName: String, val grade: Int) : Person(name, age){
    
    
   	...
}

2. Secondary construction
Any class can only have one main construction, but can have multiple secondary constructions. When a class has both primary and secondary constructors, all secondary constructors must call the primary constructor.

When defining the constructor, you can also specify a default value for the constructor. When the user calls without providing a value parameter, the default value will be used. The code is as follows:

class Student(name: String,  age: Int, val nickName: String, val grade: Int) : Person(name, age){
    
    
    constructor(name: String, age: Int, nickName: String) : this(name, age, nickName, 8) {
    
    
        
    }
    
    constructor() : this("Default", 12, "Default", 8) {
    
    
        
    }
    ...
}

How to use:

fun main() {
    
    
    val student1 = Student("lucky", 20, "luck", 9)
    val student2 = Student("Joice", 20, "joo")
    val student3 = Student()
    
    println("${
      
      student1.name} + ${
      
      student1.nickName} + ${
      
      student1.age} + ${
      
      student1.grade}")
    println("${
      
      student2.name} + ${
      
      student2.nickName} + ${
      
      student2.age} + ${
      
      student2.grade}")
    println("${
      
      student3.name} + ${
      
      student3.nickName} + ${
      
      student3.age} + ${
      
      student3.grade}")
}

//运行结果:
Lucky + luck + 20 + 9
Joice + joo + 20 + 8
Default + Default + 12 + 8

3. Ownerless structure

If the class does not use the primary structure, the subsequent inherited class does not need to use the structure to remove the inherited class (). The secondary structure can call the parent class structure superfor initialization, but the parameters of the secondary structure cannot be referenced elsewhere.

open class Person {
    
    
    var name: String = ""
    var age: Int = 0
    
    constructor(_name: String, _age: Int) {
    
    
        this.name = _name
        this.age = _age
    }
}


class Student : Person {
    
    
    constructor(name: String, age: Int, nickName: String) : super(name, age) {
    
    

    }
    
	fun study() {
    
    
        //name,age可使用
        println(name + "is studying")
        //使用nickName则会报错,若nickName是主构造的参数则可引用
        //println(nickName) 报红
    }
}

initialization block

1. initInitialization block

initIn the above Person class, a modified code block appears , which looks very similar to the static code block in Java, but their usage is quite different:

  • The static in Java means a static code block, which will be executed when the class is loaded, not when the object is created
  • The initialization code block in Kotlin will be executed when the class instance is constructed, that is, executed when the object is created

The function of the initialization code block: you can set variables or values, and perform validity checks, such as checking whether the value passed to a constructor is valid, see the following example:

open class Person (_name: String, val age: Int) {
    
    
    var name = _name;
    
	init{
    
    
        require(age > 0){
    
    "age must be positive"}
        require(name.isNotBlank()){
    
    "person must be have a name"}
    }
    
	fun printInfo() {
    
    
        println("$name 's age is $age")
    }
}

The above code is to judge the incoming value of the constructor and throw an exception.

2. Initialization sequence

Attributes can be executed in primary construction, secondary construction, and init code block, so what is their execution order:

open class Person (_name: String, val age: Int) {
    
    
    var name = _name;
    
    constructor() : this("Default", 12) {
    
    
        println("执行次构造函数")
    }
    
	init{
    
    
		println("执行init")
        require(age > 0){
    
    "age must be positive"}
        require(name.isNotBlank()){
    
    "person must be have a name"}
    }
    
	fun printInfo() {
    
    
        println("$name 's age is $age")
    }
}

Convert the above code into Java bytecode and wait for decompilation, see:

//主构造函数
public Person(@NotNull String _name, int age) {
    
    
	Intrinsics.checkNotNullParameter(_name, "_name");
	super();
	this.age = age;
	this.name = _name;
	
	String var3 = "执行init";
	boolean var4 = false;
	System.out.println(var3);
	boolean var7 = this.age > 0;
	var4 = false;
    boolean var5 = false;
    boolean var6;
    String var9;
    if (!var7) {
    
    
       var6 = false;
       var9 = "age must be positive";
       throw (Throwable)(new IllegalArgumentException(var9.toString()));
    } else {
    
    
       CharSequence var8 = (CharSequence)this.name;
       var4 = false;
       var7 = !StringsKt.isBlank(var8);
       var4 = false;
       var5 = false;
       if (!var7) {
    
    
          var6 = false;
          var9 = "person must be have a name";
          throw (Throwable)(new IllegalArgumentException(var9.toString()));
       }
   }         
}
//次构造函数
public Person() {
    
    
    this("Default", 12);
    String var1 = "执行次构造函数";
    boolean var2 = false;
    System.out.println(var1);
}

From the above, there are two construction methods, and the main constructor is called in the secondary construction, so the execution order is:

1. The first assignment is agethe attribute declared in the main constructor

2, and then the class attributename

3. Execute attribute assignment and function call in the init code block

4. Attribute assignment and function call in the secondary constructor

Reference blog:

Kotlin Basic Learning - Getting Started

Guess you like

Origin blog.csdn.net/kongqwesd12/article/details/130973821