【2025最新版Kotlin教程】Kotlin第一行代码系列第九课-委托
委托功能很强大的,但由于有一点学习难度以及不是很清晰的使用场景,常常被忽略
经验总结:你可以给任何东西委托,没有限制。
一、委托类:
// 源码联系:893151960
interface WalkListener {
fun walk()
}
class Chicken : WalkListener {
override fun walk() {
println("鸡用2只脚走路")
}
}
class Panda : WalkListener {
override fun walk() {
println("熊猫用4只脚走路")
}
}
使用示例:
/**
* @author :congge
* @date : 2023-02-03 9:58
* @desc : 委托给walkListener对象了,就不用实现WalkListener接口方法了
**/
// 方式1: 委托给传入的对象
class Animal(walkListener1: WalkListener):WalkListener by walkListener1 {
}
// 方式2:固定委托给了Chicken
class Anima2:WalkListener by Chicken() {
}
fun main() {
Animal(Chicken()).walk()
Animal(Panda()).walk()
}
二、属性代理:
fun main() {
//====================================== 委托属性start ============================================
// 方式1:最简单的委托属性 写法直接用 by ::xx
// 即值全部委托给后面的属性,后面的属性值改变,它就会跟着改变
// 它要在类中才能这样委托属性,所以建了一个Test
class Test{
var count = 100
//它们会互相影响
var total by ::count
fun printTotal(){
count = 101
println(total)
total = 102
println(count)
}
}
Test().printTotal()
// 方式2:用委托来对属性进行延迟初始化,写法 by lazy {}
// 只会在第一次调用才初始化,然后后面再调用就会直接用第一次初始化好的值
/**
* 注意:它有点讲究,就是变量只能用val,不能用var。
* 这也给你更知道它的使用场景,就是你平常的val变量,是否能用lazy懒加载
* 在Android开发中,View的声明就可以用这种方式
* 如private val tvName: TextView by lazy{ findViewById(R.id.tv_name) }
*/
val lazyValue :String by lazy {
println("computed!")
"Hello"
}
println(lazyValue)
// 方式3:类似于方式2,也是对属性延后初始化 写法 var前加 lateinit
/**
* 使用场景比较明确,我知道这个变量不可能为null,且我后面再初始化它,它的值可以不断改变
* 不像方式2,初始化一次后,值就改不了的
*/
// 因为isInitialized只能在类内调用,所以建个Test2
class Test2{
lateinit var lazyValue1:String
fun printLazyValue1(){
lazyValue1 = "123"
lazyValue1 = "456"
println(lazyValue1)
// 如果你怕没有初始化可以用isInitialized进行判断再使用
if (::lazyValue1.isInitialized){
println(lazyValue1)
}
}
}
Test2().printLazyValue1()
/**
* 选学,使用场景不多
*/
// 方式4:用by Delegates.observable 来监听设置前后两个值变化
var name: String by Delegates.observable("小象") {
prop, old, new ->
// 往往这里如果前后两个值不一样做一些逻辑,比如内容改变了,TextView控件才改变颜色
println("$old -> $new")
}
name = "小红象"
println(name)
// 方式5:看MapDemo文件
/**
* 选学,高级用法自定义委托,其实要想真正用上委托,它是必须学的
*/
// 为什么要自定义委托,比如下面param属性,它set时会自定帮我去掉空格
// 假设我要其他字符串也要这样的功能呢,你不会每个属性都写个这样的代码吧,这时自定义委托就派上用场了
class Example {
var param: String = ""
set(value) {
field = value.trim()
}
}
// 方式6:我们自定义委托,需求场景就是统一我要在get和set前加写我们的逻辑
// 通过by使用属性代理的方式,记得固定格式
var str : String by PropertyDelegate("我是代理类")
println(str)
str = "haha "
println(str)
// 忘了固定格式,看PropertyDelegate1类 可以实现ReadWriteProperty接口
var str1 : String by PropertyDelegate1("我是代理类")
println(str1)
str1 = "haha233"
println(str1)
// 方式7:如果想在自定义委托前修改或者加些判断
/**
* 这个很少用到,可忽略
*/
var str2:String by PropertyBeforeDelegate()
str2 = "haha999"
println(str2)
/**
* 使用场景1 :类的外部可以访问它的值,但不允许类的外部修改它的值
* 它叫做:属性可见性封装
*/
// 外部只能访问data值,不能修改它,因为List<String>没有add和remove方法
class SimpleTest {
val data: List<String> by ::_data
private val _data: MutableList<String> = mutableListOf()
fun load() {
_data.add("委托1")
}
}
/**
* 使用场景2:Android开发中adapter其实很适合用by lazy {}
*/
//====================================== 委托属性end ============================================
}
整个kotlin教程项目源码结构图:
有问题或者完整源码的可以看简介联系我,也可以私信我,我每天都看私信的