美文网首页
Kotlin面向对象 (1)✔️类、及属性

Kotlin面向对象 (1)✔️类、及属性

作者: 狼性代码人 | 来源:发表于2019-05-27 14:45 被阅读0次

    Kotlin语言目前还是以面向对象编程为主,函数式编程为辅。
    什么是面向对象?面向对象的三大基本特征,封装性、继承性、多态性的定义?吧啦吧啦,百度一大坨。

    一、类声明
    class 类型 {
        声明类的成员
    }
    

    kotlin中的类成员包括:构造函数、初始化代码块、成员函数、属性、内部类和嵌套类、以及对象表达式声明。

    class Animal {
        var age = 1
    
        private val weight = 0.0
    
        private fun eat() {
            // 函数体
        }
    
        fun run(): Int {
            // 函数体
            return 10
        }
    
        fun getMaxNumber(n1: Int, n2: Int) = if (n1 > n2) n1 else n2
    }
    
    二、属性
    var|val 属性名[: 数据类型] [=属性初始化]
            [getter访问器]
            [setter访问器]
    
    • 约定:中括号 ([]) 部分标示可以忽略;竖线 (|) 标示“或”关系,例如 var|val 说明可以使用 var 或 val 关键字,但两个关键字不能同时出现。
    • 注意:属性本身并不真正的保存数据,数据被保存在支持字段中,支持自动一般是不可见的,支持字段只能应用在属性访问器中,通过系统定义好的 field 变量访问。
    class Animal {
        // 名字
        var name: String = "动物"
            get() = "名称: $field"
            set(value) {
                field = "小$field"
            }
    
        var age = 2  // 年龄
            get() = if (field > 0) field else 0
    
        private val color = "yellow"  // 颜色
    }
    
    • 延迟初始化属性
      延时初始化属性声明,使用关键字lateinit;延时初始化属性要求: 不能是可空类型;只能使用var声明;lateinit关键字要方法到var之前。
    class Employee(val name: String) {
        var age: Int = 0
            get() = if (field > 0) field else 0
    
        lateinit var dept: Department
    }
    
    class Department {
        var no: Int = 0
        var name: String = ""
    
        override fun toString(): String {
            return "no=$no name=$name"
        }
    }
    
    fun main(args: Array<String>) {
        val emp = Employee("小三")
        emp.dept = Department()
        emp.dept.no = 1
        emp.dept.name = emp.name
        println(emp.dept)
    
        emp.dept = Department()
        emp.dept.no = 2
        emp.dept.name = "${emp.name} 2"
        println(emp.dept)
    }
    
    // 输出结果
    // no=1 name=小三
    // no=2 name=小三 2
    
    • 委托属性
    class User {
        var name: String by Delegate() // 1️⃣
    }
    
    class Delegate {
        operator fun getValue(thisRef: Any, property: KProperty<*>): String = property.name // 2️⃣
    
        operator fun setValue(thisRef: Any, property: KProperty<*>, value: String) { // 3️⃣
            println(value)
        }
    
    }
    
    fun main(args: Array<String>) {
        val user = User()
        user.name = "小三"  // 4️⃣
        println(user.name) // 5️⃣
    }
    
    // 输出结果
    // 小三
    // name
    

      讲解:上述代码第1️⃣行是声明委托属性,by是委托运算符,他后面的Delegate()就是属性name的委托对象,通过by运算符属性namesetter访问器被委托给Delegate对象的setValue函数,属性namegetter访问器被委托给Delegate对象的getValue函数。Delegate对象不必实现任何借口,只需实现getValuesetValue函数即可,即见代码第2️⃣和第3️⃣行。注意这两个函数前面都有operator关键字修饰,operator所修饰的函数是运算符重载函数,本例中说明了setValuegetValue函数重载by运算符。代码第4️⃣行给name属性赋值,这会调用委托对象的setValue函数,代码第5️⃣行是读取name值,这会调用委托对象的getValue函数。

    • 惰性加载属性
      惰性加载属性与延时加载属性类似,只是第一次访问该属性时才进行初始化。不同的是惰性加载属性使用 lazy 函数声明委托属性,而延时初始化属性使用 lateinit 关键字修饰属性。还有惰性加载属性必须是 val 的,而延迟初始化属性必须是 var 的。
    open class Employee {
        var no: Int = 0
    
        var firstName = "Tony"
        var lastName: String = "Guan"
        val fullName by lazy { "$firstName.$lastName" } // 1️⃣
    
        lateinit var dept: Department:
    }
    
    class Department {
        var no: Int = 0
        var name: String = ""
    
        override fun toString(): String {
            return "no=$no name=$name"
        }
    }
    
    fun main(args: Array<String>) {
        val emp = Employee()
        println(emp.fullName)   // Tony.Guan
    
        val dept = Department()
        dept.no = 20
    
        emp.dept = dept
        println(emp.dept)
    }
    

      讲解:代码第1️⃣行声明了惰性加载属性fullNameby 后面是 lazy 函数,注意 lazy 不是关键字,而是函数。lazy 函数后面跟着的是尾随 Lambda 表达式。惰性加载属性使用 val 声明。

    • 可观察属性
    class Department {
        var no = 0
        
        var name: String by Delegates.observable("无") { property, oldValue, newValue ->  // 1️⃣
            println("$oldValue -> $newValue")
        }
    }
    
    fun main(args: Array<String>) {
        val dept = Department()
        dept.no = 20
        dept.name = "技术部"   // 输出 无 -> 技术部
        dept.name = "市场部"   // 输出 技术部 -> 市场部
    }
    

      讲解:代码第1️⃣行是声明 name 委托属性,by 关键字后面的Delegates.observable()函数有两个参数:第一个参数是委托属性的初始化值,第二个参数是属性变化事件的响应器,响应器是函数类型,具体调用时可使用 Lambda 表达式作为实际参数。在 Lambda 表达式中有三个参数,其中property是属性,oldValue是属性的旧值,newValue是属性的新值。

    相关文章

      网友评论

          本文标题:Kotlin面向对象 (1)✔️类、及属性

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