Kotlin 构造函数、SAM 接口、可见性修饰符

157 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第24天,点击查看活动详情

一、构造函数

1)、主构造函数的特点是没有函数体,直接跟在类名的后面即可,如果需要在主构造函数里面做逻辑,复写 init 函数即可

2)、主构造函数中声明成 val 或者 var 的参数将自动成为该类的字段,如果不加,那么该字段的作用域仅限定在主构造函数中

3)、构造函数是通过 constructor 关键字来定义的,当主构造函数无修饰符修饰的时候,可省略 constructor 关键字

4)、当一个类没有显示的定义主构造函数,但是定义了次构造函数时,那么被继承的类后面不需要加 ()

记住一个小技巧: Kotlin 中规定,需要显示的去声明调用的父类的构造函数

//情况1 定义一个主构造函数,无修饰符省略 constructor,定义一个 attr 属性
class ConstructorClass1 (var attr: String){
  
}

//情况2 定义一个主构造函数,使用修饰符修饰 constructor,定义一个 attr1 属性和一个 attr2 属性
class ConstructorClass2 @JvmOverloads constructor(var attr1: String,var attr2: Int){
  
}

//情况3 当一个类没有显示的定义主构造函数,但是定义了次构造函数时,那么被继承的类后面不需要加 ()
open class ParentClass(var attr1: String,var attr2: Int)

class ConstructorClass3 : ParentClass{

    constructor(attr1: String,attr2: Int) : super(attr1,attr2){

    }
}

//情况4 复写 init 代码块做一些初始化逻辑
class ConstructorClass4(var attr1: String){


    init {
        println("调用了 init 代码块1")
    }

    init {
        println("调用了 init 代码块2")
    }

    constructor() : this("erdai666"){
        println("调用了次构造函数")
    }
}

fun main() {
   ConstructorClass4()
}
//打印结果
调用了 init 代码块1
调用了 init 代码块2
调用了次构造函数

//情况5
open class ConstructorClass5(attr1: String){

    val firstProperty = "First property: $attr1".also(::println)

    init {
        println("调用了ConstructorClass5 init 代码块1")
    }

    val secondProperty = "Second property: $attr1".also(::println)

    init {
        println("调用了ConstructorClass5 init 代码块2")
    }

    constructor() : this("erdai666"){
        println("调用了 ConstructorClass5 次构造函数")
    }
}

class SubConstructorClass5 : ConstructorClass5{

    constructor() : super(){
        println("调用了 SubConstructorClass5 次构造方法")
    }

    init {
        println("调用了SubConstructorClass5 init 代码块1")
    }
}

fun main() {
   SubConstructorClass5()
}

//打印结果
First property: erdai666
调用了ConstructorClass5 init 代码块1
Second property: erdai666
调用了ConstructorClass5 init 代码块2
调用了 ConstructorClass5 次构造函数
调用了SubConstructorClass5 init 代码块1
调用了 SubConstructorClass5 次构造方法

根据上述打印我们可以得出 Kotlin 中构造函数调用的一些结论:

1、调用构造函数前的隐式三步骤

1、调用父类的构造方法

2、初始化本类所有属性

3、初始化本类的 init 函数块

其中 2 和 3 是按照顺序从上往下执行的

2、继承结构的代码调用顺序:

1、初始化父类的属性和 init 函数块

2、初始化父类的构造方法

3、初始化本类的属性和 init 函数块

4、初始化本类的构造方法

二、SAM 接口

1、单抽象方法接口称为函数式接口或者 SAM(Single Abstract Method) 接口

2、SAM 转换就是将函数式接口的创建使用带接口类型前缀的 Lambda 表达式替换

fun interface IntPredicate {
   fun accept(i: Int): Boolean
}

// 匿名内部类方式创建一个实例对象
val isEven = object : IntPredicate {
   override fun accept(i: Int): Boolean {
       return i % 2 == 0
   }
}

// Lambda 表达式方式创建一个实例对象
val isEven = IntPredicate { it % 2 == 0 }

三、可见性修饰符

类比 Java,如下表:

修饰符JavaKotlin
public所有类可见所有类可见(默认)
private当前类可见当前类可见
protected当前类,子类,同一个包下的可见当前类和子类可见
default同一个包下的可见(默认)
internal同一个模块中的类可见

四、总结

本篇文章我们介绍了:

1、Kotlin 中的构造函数,并且通过 Log 打印得出了构造函数执行的一些结论

2、SAM 接口又称单抽象方法接口,这种接口我们可以使用带接口类型前缀的 Lambda 表达式进行接收

3、类比 Java 讲了 Kotlin 中的可见性修饰符

好了,本篇文章到这里就结束了,希望能给你带来帮助 🤝