Android Kotlin 扩展和委托(六)

首先申明下,本文为笔者学习《Kotlin 程序开发入门精要》的笔记,并加入笔者自己的理解和归纳总结。

1. 扩展

1.1 类成员扩展

扩展可以向类中添加成员。为Long添加一个format方法,用于时间戳格式化输出。

fun Long.format(): String {
    return SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
            .format(Date(this * 1000))
}

fun main(args : Array<String>) {
    var time : Long = 1585891747
    println(time.format());  // 2020-04-03 01:29:07
}

因为open不能用于顶层函数,所以扩展不能用于继承。

open class Super {
}

class Child : Super() {
}

fun Super.add(value : Int) = value + 10

fun Child.add(value : Int) = value + 100

fun main(args : Array<String>) {
    var s1 : Super = Super()
    var s2 : Super = Child()
    var s3 : Child = Child()

    println(s1.add(5))  // 15
    println(s2.add(5))  // 15
    println(s3.add(5))  // 105
}

如果通过扩展向类中添加的成员函数与类中原来的成员函数的结构完全相同,内部成员函数的优先级更高。

class Operation {
    fun add(value : Int) : Int {
        return value + 10
    }
}

fun Operation.add(value : Int) : Int {
    return value + 100
}

fun main(args : Array<String>) {
    var op = Operation()
    println(op.add(5))  // 15 
}

1.2 类属性扩展

扩展属性没有backing field属性,因此保存和获取属性值都需要一个类成员变量。

class Operation {
    var i:Int = 0
}

var Operation.value : Int
        get() = i
        set(v : Int) {
            i = v
        }

fun main(args : Array<String>) {
    var op = Operation()
    op.value = 10
    println(op.value)  // 10
}

1.3 伴随对象扩展

可以为伴随对象添加成员

class Shape {
    companion object Factory {	 
    }	
}

fun Shape.Factory.create() : Shape {
    return Shape()
}

fun main(args : Array<String>) {
    var s = Shape.create()
}

1.4 类中扩展

在类中也可以使用扩展

open class Base {
    fun sub() {
        println("Base.sub")
    }
}

open class BaseHolder {

    open fun Base.add() {
        println("Base.add in BaseHolder")
    }

    fun test(b : Base) {
        b.add()
        b.sub()
    }
}

fun main(args : Array<String>) {
    BaseHolder().test(Base())
}

输出

Base.add in BaseHolder
Base.sub

类中的扩展可以被继承

open class SubHolder : BaseHolder() {

    override fun Base.add() {
        println("Base.add in SubHolder")
    }

}

fun main(args : Array<String>) {
//    BaseHolder().test(Base())
    SubHolder().test(Base())
}

输出

Base.add in SubHolder
Base.sub

2. 委托

委托可以将代码放在同一个地方,以便被多个类和属性重用。

2.1 类的委托

通过使用by关键字来实现类的委托。Car继承(Engine),通过by关键字把run()方法委托给一个对象(Engine),这个对象通过主构造器传入。

interface Engine {
    fun run()
}

class EngineImpl : Engine {
    override fun run() {
        println("Engine run")
    }
}

class Car(engine : Engine) : Engine by engine {
}

fun main(args : Array<String>) {
    Car(EngineImpl()).run()
}

2.2 类属性委托

类属性委托需要创建委托类,委托类需要创建getValue()setValue()两个函数,函数使用operator声明。

import kotlin.reflect.KProperty

class Teacher {
    // 将name属性委托给Delegate类
    var name: String by Delegate()
}

class Student {
    // 将name属性委托给Delegate类
    var name: String by Delegate()
}

class Delegate {
    var name: String = ""

    operator fun getValue(thisRef : Any?, property : KProperty<*>) : String {
        println("Delegate.getValue 被调用")
        return name
    }

    operator fun setValue(thisRef : Any?, property : KProperty<*>, value : String) {
        println("Delegate.setValue 被调用")
        this.name = value;
    }
}

fun main(args: Array<String>) {
    var t: Teacher = Teacher()
    t.name = "Mike"
    println(t.name)

    var s: Student = Student()
    s.name = "Jack"
    println(s.name)
}

输出

Delegate.setValue 被调用
Delegate.getValue 被调用
Mike
Delegate.setValue 被调用
Delegate.getValue 被调用
Jack

可以向委托类的主构造传入一个初始化函数,initializer是初始化函数,返回对应类名

class Teacher {
    var name: String by Delegate {
        "Teacher"
    }
}

class Student {
    var name: String by Delegate {
        "Student"
    }
}

class Delegate<T>(initializer : () -> T) {
    var name: String = ""
    var className = initializer()

    operator fun getValue(thisRef : Any?, property : KProperty<*>) : String {
        println("${className}.getValue 被调用")
        return name
    }

    operator fun setValue(thisRef : Any?, property : KProperty<*>, value : String) {
        println("${className}.setValue 被调用")
        this.name = value;
    }
}

fun main(args: Array<String>) {
    var t: Teacher = Teacher()
    t.name = "Mike"
    println(t.name)

    var s: Student = Student()
    s.name = "Jack"
    println(s.name)
}

输出

Teacher.setValue 被调用
Teacher.getValue 被调用
Mike
Student.setValue 被调用
Student.getValue 被调用
Jack

2.3 标准委托

惰性加载

lazy接受一个表达式作为参数,第一次调用时执行表达式,并记住执行结果。后面所用的调用只会返回记住的结果。

val value : String by lazy {
    println ("lazy load")
    "Hello World"
}

fun main(args : Array<String>) {
    println(value)
    println(value)
}

输出

lazy load
Hello World
Hello World

可观察属性

Delegates.observable实现可观察属性值变化。

class Person {
    // Mike是初始值
    var name : String by Delegates.observable("Mike") {
        prop, oldValue, newValue ->
            println("oldValue = $oldValue, newValue = $newValue")
    }
}

fun main(args : Array<String>) {
    var p = Person()
    p.name = "Jack"
    p.name = "Peter"
}

输出

oldValue = Mike, newValue = Jack
oldValue = Jack, newValue = Peter

可阻止属性赋值

Delegates.voteable能够拦截属性赋值操作。voteable函数会返回一个布尔类型的值,如果是true,表示允许给属性赋值。

class Person {

    var name : String by Delegates.vetoable("Mike") {
        prop, oldValue, newValue ->
            println("oldValue = $oldValue, newValue = $newValue")

            var result = true
            if (newValue.equals("Peter")) {				
                result = false
            }
            result
    } 
}

fun main(args : Array<String>) {
    var p = Person()
    p.name = "Jack"
    p.name = "Peter"
    println(p.name)
}

输出

oldValue = Mike, newValue = Jack
oldValue = Jack, newValue = Peter
Jack

Map委托

Map委托通过将Map中的key的值映射到同名的属性中。

class Person (var map : Map<String, Any>) {

    val name : String by map
    val age : Int by map

}

fun main(args : Array<String>) {
    var map = mapOf(
        "name" to "Mike",
        "age" to 25
    )

    var p = Person(map)
    println(p.name)
    println(p.age)
}

输出

Mike
25

MutableMap委托
MutableMap委托可以和属性值同步变化

class Person (var map : MutableMap<String, Any>) {

    var name : String by map
    var age : Int by map

}

fun main(args : Array<String>) {
    var map = mutableMapOf(
            "name" to "Mike",
            "age" to 25
    )

    var p = Person4(map)
    println(p.name)
    println(p.age)

    map.put("name", "Jack")
    println(p.name)

    p.age = 35
    println(map)
}

输出

Mike
25
Jack
{name=Jack, age=35}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值