Kotlin系列——构造函数精讲

1.关键字:

constructor

关键字可以省略,但是如果构造函数有注解或可见性修饰符,则关键字不可省,如设置构造函数为私有

class Person private constructor(){
    lateinit var name: String
    var age: Int = 0
    var parent: Person? = null
    constructor(name: String, age: Int, child: Person):this(){
        child.parent = this
        this.name = name
        this.age =age
    }
    constructor(name: String, age: Int):this() {

        this.name = name
        this.age =age
    }

}

如果不存在次构造函数,默认存在一个开发的主构造函数,添加 private 修饰为私有构造函数

2.直接在跟在类名后面的是主构造函数,主构造函数constructor可以省略
3.主构造函数和次构造函数可以共存,但是如果存在主构造方法,那么次构造函数需要直接或者间接的委托主构造函数

class Person(name:String){
    var name: String = name
    var age: Int = 0
    var parent: Person? = null
    constructor(name: String, age: Int, child: Person) :this(name,age){
        child.parent = this
        this.name = name
        this.age =age
    }
    constructor(name: String, age: Int):this(name) {
        this.name = name
        this.age =age
    }

}

4.如果不存在主构造函数,多个次构造函数可以共存,且不用委托

class Person{
    var name: String
    var age: Int 
    var parent: Person? = null
    constructor(name: String, age: Int, child: Person){
        child.parent = this
        this.name = name
        this.age =age
    }
    constructor(name: String, age: Int) {
        this.name = name
        this.age =age
    }

}

5.主构造函数中不能代码,但是Kotlin提供一个init初始代码块

//init代码块
class Person  constructor(){
    lateinit var name: String
    var age: Int = 0
    var parent: Person? = null
    init {
        println("I am init")
        println("name = $name,age=$age,parent = $parent")
    }
    constructor(name: String, age: Int, child: Person):this(){
        child.parent = this
        this.name = name
        this.age =age
    }
    constructor(name: String, age: Int):this() {

        this.name = name
        this.age =age
    }

}

注意

(1) 如果存在主构造函数,类的属性必须存在初始化值或者用延迟加载关键字lateinit。但是 lateinit只能修饰非Kotlin基础类型,如String等

(2)init初始块在优先执行(次构造函数之前执行),如果执行过程中延迟加载的变量没有赋值,会报异常

Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property name has not been initialized

(3) lateinit只能用于类体的var属性,不能用于构造函数中
(4) lateinit不能用于拥有定制gettersetter方法的属性

6.主构造函数的多种表示法

//主构造函数 直接定义属性
class Person(var name: String, var age: Int) {

}

//主构造函数 只传递参数 函数体内赋值
class Person1(name: String, age: Int) {
    var name = name
    val age = age
}

7.构造函数属性可以函数类型

////主构造函数 属性为函数类型
class Person( num1: Int,  num2: Int,operator:(Int,Int)->Int) {
   lateinit var name :String

   init {
      println("operator = ${operator(num1,num2)}")
   }
   constructor(num1: Int, num2: Int):this(num1,num2,operator = {x,y->x+y}){

   }

}

8.属性

(1) var 默认有一般的公开getter和setter属性,可以直接通过.进行赋值和取值;

(2) val 默认有一般的公开getter,可以直接通过.进行取值,没有setter方法;

(3)属性定制;

  • 订制为私有 private set , 没有 private get,如果想属性不被公开,直接在属性前面添加private
  • 在get 和 get中不可以使用属性,否则会造成循环引用,Kotlin使用幕后字段field解决无限循环问题,所有需要使用字段自身的地方用field代替
  • get 和set可以任意定制,定义其中一个的话,另一个则为默认
///主构造函数 属性getter 和setter
class Person(age: Int) {

    //重写get和set方法
    var name: String = ""
        get() = "My name is" + field
        set(value) {
            field = value
        }

    var age: Int = age
        set(value) {
            field = value
            if (value >= 18) {
                isAdult = true
            }
        }

    //   属性定制为私有
    var isAdult: Boolean = false
        private set

    var addAge: Int = 0
        get() {
            return field + 1
        }
        set(value) {
            field = value
            age += value
        }

    constructor(age: Int, name: String) : this(age) {
        this.name = name
    }

    override fun toString(): String {
        return "name =$name,age=$age,isAdult = $isAdult,addAge = $addAge"
    }
}

9.编译期常量

关键字:const

只能修饰 val

特点:
- 只能位于顶层或者object的成员,不能修饰一般类成员
- 只能修饰原始数据类型和String
- 没有自定义getter方法
- 区别val 和const val :str1 在传递的过程中是引用str1,str2在传递的过程中是传递str2的值”Hello Kotlin”

Kotlin代码

package `object`

val str1 = "Hello Kotlin"
const val  str2 = "Hello Kotlin"

fun main(args: Array<String>) {
    var str3 = str1
    var str4 = str2
}

反编译成java代码

public final class ConstTestKt {
   @NotNull
   private static final String str1 = "Hello Kotlin";
   @NotNull
   public static final String str2 = "Hello Kotlin";

   @NotNull
   public static final String getStr1() {
      return str1;
   }

   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      String str3 = str1;
      String str4 = "Hello Kotlin";
   }
}

猜你喜欢

转载自blog.csdn.net/qq_26585943/article/details/80275426