美文网首页
一些对Kotlin委托的理解

一些对Kotlin委托的理解

作者: 蜗牛是不是牛 | 来源:发表于2023-01-05 14:16 被阅读0次

前言

委托(Delegation),可能是 Kotlin 里最容易被低估的特性。

提到 Kotlin,大家最先想起的可能是 扩展 ,其次是协程 ,再要不就是空安全 ,委托根本排不上号。但

是,在一些特定场景中,委托的作用是无比犀利的。

委托类(Class Delegation)

委托类,通过关键字 by 可以很方便的实现语法级别的 委托模式 。看个简单例子:

interface DB {
fun save()
}
class SqlDB() : DB {
override fun save() { println("save to sql") }
}
class GreenDaoDB() : DB {
override fun save() { println("save to GreenDao") }
}
// 参数 通过 by 将接口实现委托给 db
// ↓ ↓
class UniversalDB(db: DB) : DB by db
fun main() {
UniversalDB(SqlDB()).save()
UniversalDB(GreenDaoDB()).save()
}
/*
输出:
save to sql
save to GreenDao
*/

这种委托模式在我们实际编程中十分常见,UniversalDB 相当于一个壳,它提供数据库存储功能,但并不关心它

怎么实现。具体是用 Sql 还是 GreenDao,传不同的委托对象进去就行。

以上委托类的写法,等价于以下 Java 代码:

class UniversalDB implements DB {
DB db;
public UniversalDB(DB db) { this.db = db; }
// 手动重写接口,将 save 委托给 db.save()
@Override// ↓
public void save() { db.save(); }
}

各位可不要小看这个小小的 by ,上面的例子中,接口只有一个方法,所以 Java 看起来也不怎么麻烦,但是,当

我们想委托的接口方法很多的时候,这个 by 能极大的减少我们的代码量。

我们看一个复杂点的例子,假设我们想对 MutableList 进行封装,并且增加一个方法,借助委托类的 by ,几
行代码就搞定了:


class LogList(val log: () -> Unit, val list: MutableList<String>) : MutableList<String> by
list{
fun getAndLog(index: Int): String {
log()
return get(index)
}
}

如果是在 Java 里,那就不好意思了,呵呵,我们必须 implements 这么多方法:


image.png

想想要写那么多的重复代码就心累,是不是?

注:Effective Java 里面提到过:组合优于继承(Favor composition over inheritance),所以在 Java 中,我
们也会尽可能多使用接口(interface)。借助 Kotlin 提供的委托类,我们使用组合类会更方便。结合上面的例子,如果需要实现的接口有很多个,委托类真的可以帮我们省下许多的代码量。

委托属性(Property Delegation)

委托属性 ,它和委托类虽然都是通过 by 来使用的,但是它们完全不是一回事。委托类委托出去的是它的接口实

现;委托属性,委托出去的是属性的 getter , setter 。我们前面经常提到的 val text = by lazy{} ,其实就是将 text的 getter 委托给了 lazy{}

val text: String = by lazy{}
// 它的原理其实跟下面是一样的
// 语法层面上是等价的哈,实际我们不能这么写
val text: String
get() { lazy{} }

自定义委托属性

Kotlin 的委托属性用起来很神奇,那我们怎么根据需求实现自己的属性委托呢?看看下面的例子:

class Owner {
var text: String = “Hello”
}

我想为上面的 text 属性提供委托,应该怎么做?请看下面例子的注释:

class StringDelegate(private var s: String = "Hello") {

operator fun getValue(thisRef: Owner, property: KProperty<*>): String {
return s
}

operator fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {
s = value
}
}
class Owner {

var text: String by StringDelegate()
}

小结:

  • var —— 我们需要提供 getValue 和 setValue
  • val —— 则只需要 getValue
  • operator —— 是必须的,这是编译器识别委托属性的关键。
  • property —— 它的类型一般固定写成 KProperty<*>
  • value —— 的类型必须是委托属性的类型,或者是它的父类。也就是说例子中的 value: String 也可以
    换成 value: Any 。
  • thisRef —— 它的类型,必须是属性所有者的类型,或者是它的父类。也就是说例子中的 thisRef:Owner 也可以换成 thisRef: Any 。

以上是委托属性中比较重要的细节,把握好这些细节,我们写自定义委托就没什么问题了。

相关文章

  • 一些对Kotlin委托的理解

    前言 委托(Delegation),可能是 Kotlin 里最容易被低估的特性。 提到 Kotlin,大家最先想起...

  • Kotlin中的委托

    Kotlin中的委托 啥是委托 其实kotlin中的委托的理念就是委托模式也是叫做代理模式;在Kotlin中委托有...

  • Kotlin的by 委托

    Kotlin的by 委托 1. by lazy的原理解析 我们用kotlin经常会用到by lazy,所以我之前一...

  • Kotlin 委托

    Kotlin 委托 1. 类委托 在 Kotlin 中用 by 关键字来表示委托 1. 类委托的第一种实现方式 T...

  • Kotlin委托

    Kotlin委托 1.Kotlin中的委托有两种形式,一种是委托模式,一种是委托属性。 2.委托模式是设计模式中的...

  • Kotlin-类委托(delegation)

    Kotlin-类委托(delegation) 我们用Java可以实现委托的功能,但是在Kotlin这个语言直接就已...

  • Kotlin - 关于类的委托的理解

    无论是Kotlin官方的文档和别的地方的文档,你都能发现所有讲类的委托都会举这样一个例子 上述代码什么意思呢? b...

  • kotlin委托

    JAVA代理模式 代理模式定义 为其他对象提供一种代理以控制对象对这个对象的访问。 代理模式的使用场景 当无法或不...

  • Kotlin -- 委托

    在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。 类委托 由输出结果可以看...

  • Kotlin委托

    类委托 设计大型的面向对象系统的一个常见问题就是由继承的实现导致的脆弱性。当你扩展一个类并重写某些方法时,你的代码...

网友评论

      本文标题:一些对Kotlin委托的理解

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