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

2019-05-27  本文已影响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"  // 颜色
}
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函数。

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是属性的新值。

上一篇下一篇

猜你喜欢

热点阅读