Kotlin面向对象总结-延迟初始化与主从构造函数

延迟初始化: by lazy 和 lateinit

by lazy

class PayFlyAnimal(val weight: Double, val age: Int, val color: String) {

    val sex: String by lazy {
        if (color == "yellow") "male" else "female"
    }
}

fun main() {
    val a = PayFlyAnimal(2.00, 2, "blue")
    println(a.sex)
}

female

by lazy语法特点

1.该变量必须是引用不可变的(val),而不能通过var来声明。

2.在被首次调用时,才会进行赋值操作。一旦被赋值,后续它将不能被更改。

lazy的背后是接受一个lamdba并返回一个Lazy<T>实例的函数,第一次访问该属性时,会执行lazy对应的Lambda表达式并记录结果,后续访问该属性时只是返回记录的结果。

另外系统会给lazy属性默认加上同步锁,也就是LazyThreadSafetyMode.SYNCHRONIZED,它在同一时刻只允许一个线程对lazy属性进行初始化,所以它是线程安全的。

如果认为该属性可以并行执行,没有线程安全问题,那么可以给lazy传递 LazyThreadSafetyMode.PUBLICATION参数。还可以给lazy传递LazyThreadSafetyMode.NONE参数,这将不会有任何线程方面的开销,当然也不会有任何线程安全的保证。

val sex2: String by lazy(LazyThreadSafetyMode.PUBLICATION) {
    //并行模式
    if (color == "yellow") "male" else "female"
}

val sex3:String by lazy(LazyThreadSafetyMode.NONE) {
    //不做任何线程保证也不会有任何线程开销
    if (color == "yellow") "male" else "female"
}

lateinit主要用于var声明的变量,它不能用于基本数据类型,如Int,Long,所以需要使用 包装类替代。

class PayFlyAnimal2(val weight: Double, val age: Long, val color: String) {
    lateinit var sex: String
    var count by Delegates.notNull<Long>()

    fun printSexAndCount() {
        this.sex = if (color == "yellow") "male" else "female"
        this.count = 666
        println("sex:" + this.sex + ",count:" + this.count)
    }
}

sex:female,count:666

Delegates.notNull<T>

用var声明的基本数据类型变量也是可以延迟初始化的,可以通过Delegates.notNull<T>实现。

可以发现Kotlin不主张使用Java中的构造方法重载,来解决多个构造参数组合调用的问题。取而代之的是利用构造参数默认值以及使用val、var来声明构造函数的语法。

主从构造方法

Kotlin中的多构造方法之间建立了“主从”的关系。

1.通过constructor方法定义了一个新的构造方法,称为从构造方法。相应地,在类外部定义的构造方法称为主构造方法。每个类最多存在一个主构造方法和多个从构造方法,如果主构造方法存在注解或可见性修饰符, 也必须像从构造方法一样加上constructor关键字。

class PayKBird(age: Int) {
    val age: Int

    init {
        this.age = age
    }

    constructor(newAge: Int, content: String) : this(newAge) {
        println("content:$content")
    }
}

val payKBird = PayKBird(12, "Bird")
println(payKBird.age)

content:Bird
12
class PayKBird constructor(age:Int) {}
internal class PayKBird2  @JvmOverloads constructor(age:Int) {}

每个从构造方法由两部分组成。一部分是对其他构造方法的委托,另一部分是由花括号包裹的代码块。执行顺序上会先执行委托的方法,然后执行自身代码块的逻辑。

通过this关键字来调用要委托的构造方法。如果一个类存在主构造方法,那么每一个从构造方法都要直接或间接地委托给它。

例子:

class PayKBird3(strDate: String) {
    val payDate: String = strDate

    constructor(timeStamp: Long) : this(Date(timeStamp))

    constructor(date: Date) : this(SimpleDateFormat("yyyy-MM-dd").format(date))
    
}

fun main() {
    val payKBird3 = PayKBird3(System.currentTimeMillis())
    println(payKBird3.payDate)
}

2020-02-04

利用从构造方法就可以使用不同参数来初始化第三方类库中的类。最典型的例子是定制业务中特殊的View类。

class KView : View {

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attributes: AttributeSet?) : this(context, attributes, 0)

    constructor(context: Context, attributes: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attributes,
        defStyleAttr
    ) {

    }
}

参考 kotlin核心编程 

发布了166 篇原创文章 · 获赞 162 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/zhangying1994/article/details/104165581