美文网首页
kotlin基础--类定义、初始化、继承

kotlin基础--类定义、初始化、继承

作者: aruba | 来源:发表于2021-08-22 15:51 被阅读0次

    上次介绍了kotlin中的集合List、Set、Map的操作,接下来介绍kotlin中如何定义类、初始化、继承

    一、类的定义

    1.field

    对于每个属性,kotlin会自动生成一个的field:代表属性的值,一个getter方法,一个setter方法。我们操作属性时,实际调用的是get和set方法,因为kotlin变量的不可空性,对于非空变量,我们在赋值时,系统要对赋值的值进行是否为null判断

    class Human {
        var name: String? = null
        var age: Int = 5
    }
    

    我们可以自定义get和set方法,需要写在对应变量的下面

    class Human {
        var name: String? = null
            get() {
                //如果不是null,返回首字母大写,否则返回"Null"字符串
                return field?.capitalize() ?: "Null"
            }
            set(value) {
                //value为null,赋值成"Null"字符串,否则赋值成小写字符串
                field = value?.toLowerCase() ?: "Null"
            }
        var age: Int = 5
            set(value) {
                //负数抛出异常
                require(value > 0) { "不能为负数" }
                field = value
            }
    }
    
    2.计算属性

    get和set也可以直接赋值成表达式

    class Human2 {
        var name: String? = null
        val age
            //年龄为随机数
            get() = (1..100).shuffled().first()
    }
    
    3.防范竞态条件

    和可空变量一样,如果属性可空,那么使用它的时候必须保证它非空

    class Human2 {
        var name: String? = null
        val age
            //年龄为随机数
            get() = (1..100).shuffled().first()
    
        fun capitalizeName() {
            name = name?.capitalize()
        }
    }
    

    二、初始化

    和Java实例化有很多不同,kotlin的初始化更加灵活

    1.主构造函数

    在类的定义头中定义主构造函数,使用临时变量为属性赋值

    class Human3(
        _age: Int,
        _name: String
    ) {
        var name: String? = _name
        var age = _age
    }
    
    2.在主构造函数定义属性

    kotlin允许直接用一个定义,同时指定类属性和参数

    class Human4(
        _name: String,
        var age: Int
    ) {
        var name: String? = _name
    }
    
    3.次构造函数

    使用constructor来创建次构造函数

    class Human5(
        _name: String,
        var age: Int
    ) {
        var name: String? = _name
    
        constructor(_name: String) : this(_name, age = 0) {
            this.name = _name.toLowerCase()
        }
    }
    
    4.默认参数值

    定义构造函数时,可以指定参数值,如果用户不提供,则使用默认值

    class Human6(
        _name: String,
        var age: Int = 10
    ) {
        var name: String? = _name
    }
    
    fun main() {
        val h4 = Human6(_name = "张三")
        println(h4.name)
        println(h4.age)
    }
    

    结果:
    张三
    10

    5.初始化块

    初始化块,相当于默认提供了一个初始化方法,可以设置变量或值,以及执行有效性检查,初始化块在实例化时执行

    class Human7(
        _name: String,
        var age: Int = 10
    ) {
        var name: String? = _name
    
        init {
            name = name?.capitalize()
        }
    }
    
    6.初始化顺序

    kotlin代码和反编译成Java代码对比:


    7.延迟初始化

    使用关键字lateinit来表示使用时,才初始化参数,构造时并不会初始化占用内存
    可以执行isInitialized检查是否初始化

    class Human8(
        _name: String,
        var age: Int = 10
    ) {
        var name: String? = _name
    
        lateinit var gender: String
    
        fun isGenderInit(): Boolean {
            return ::gender.isInitialized
        }
    }
    
    fun main() {
        val h8 = Human8(_name = "zhangsan")
        println(h8.isGenderInit())
    }
    

    结果:
    false

    8.惰性初始化

    惰性初始化也可以实现延迟初始化

    class Human9(
        _name: String,
        var age: Int = 10
    ) {
        var name: String? = _name
    
        val gender by lazy { genderInit() }
    
        private fun genderInit(): String {
            println("init ${System.currentTimeMillis()}")
            return "0"
        }
    }
    

    测试:

    fun main() {
        println("start ${System.currentTimeMillis()}")
        val h9 = Human9(_name = "zhangsan")
    
        Thread.sleep(3000)
    
        println(h9.gender)
        println("end ${System.currentTimeMillis()}")
    }
    

    结果:
    start 1629701476608
    init 1629701479710
    0
    end 1629701479710

    三、继承

    1.类继承

    kotlin默认每个类都是封闭的,如果要开放继承,使用关键字"open"

    open class Human(
        var name: String,
        var age: Int
    ) {
    
    }
    
    class female(
        _name: String,
        _age: Int,
        var height: Int = 0
    ) : Human(_name, _age) {
    
    } 
    
    2.函数重载

    父类函数也需要"open"关键字修饰才能重载,并且重载的函数要加上"override"关键字

    open class Human(
        var name: String,
        var age: Int
    ) {
        open fun work() = "Human working"
    }
    
    class Female(
        _name: String,
        _age: Int,
        var height: Int = 0
    ) : Human(_name, _age) {
        override fun work() = "female working"
    }
    
    fun main() {
        val h: Human = Female("tom", 18)
        println(h.work())
    }
    
    

    结果:
    female working

    3.类型检测

    Java中使用:”instanceof“ ,kotlin中使用:”is“

    fun main() {
        val h: Human = Female("tom", 18)
        println(h.work())
    
        println(h is Human)
    }
    
    4.类型转换

    Java强转类型使用(类名),kotlin使用"as"关键字

    open class Human(
        var name: String,
        var age: Int
    ) {
        open fun work() = "Human working"
    }
    
    class Female(
        _name: String,
        _age: Int,
        var height: Int = 0
    ) : Human(_name, _age) {
        override fun work() = "female working"
    
        fun sleep() = "sleep"
    }
    
    fun main() {
        val h: Human = Female("tom", 18)
        println(h.work())
    
        println(h is Human)
    
        println((h as Female).sleep())
    }
    
    5.智能类型转换

    如果类型转换过,下次使用时不再需要转换

    fun main() {
        val h: Human = Female("tom", 18)
        println(h.work())
    
        println(h is Human)
    
        println((h as Female).sleep())
        println(h.sleep())
    }
    
    6.超类

    kotlin中所有类的超类为Any,编译时才会实现它的基本方法,以便根据不同平台实现跨平台

    相关文章

      网友评论

          本文标题:kotlin基础--类定义、初始化、继承

          本文链接:https://www.haomeiwen.com/subject/wbokiltx.html