Android-Daily-Interview icon indicating copy to clipboard operation
Android-Daily-Interview copied to clipboard

2019-07-26:什么是委托属性?请简要说说其使用场景和原理?

Open Moosphan opened this issue 4 years ago • 6 comments

Moosphan avatar Jul 26 '19 01:07 Moosphan

把一件事委托给其他人来做。如kotlin中的by var p: String by Delegate(),get和set委托给Delegate的getValue()方法和setValue()方法

18361237136 avatar Jul 30 '19 09:07 18361237136

居然没人说,很奇怪呀=.=

  1. by lazy: 用于 延迟初始化
  2. 自定义委托,不如我想获取一个 用户id,那么他是在 本地数据库中的,那么我就可以
private val userId by UserIdDelegete()

UserIdDelegete中 定义了 user id 的获取和设置方法

写的不一定对哈,用的不多,也记不住

  1. butterknife好像有个kotlin 版本的 ,用于id查找,可以参考,很优秀

原理的话不太好写,但是可以借助于 kotlin byteCode 工具来看自动生成的代码,类委托的话大家自己百度吧,简单对比一下属性委托

//源文件

class A {
    private var name by Delegate()
}

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, 这里委托了 ${property.name} 属性"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef 的 ${property.name} 属性赋值为 $value")
    }
}

ByteCode 工具decompile的java文件

public final class Delegate {
   @NotNull
   public final String getValue(@Nullable Object thisRef, @NotNull KProperty property) {
      //将属性传递过来,如果只有一个,直接写获取的逻辑就好
      Intrinsics.checkParameterIsNotNull(property, "property");
      return thisRef + ", 这里委托了 " + property.getName() + " 属性";
   }

   public final void setValue(@Nullable Object thisRef, @NotNull KProperty property, @NotNull String value) {
      Intrinsics.checkParameterIsNotNull(property, "property");
      Intrinsics.checkParameterIsNotNull(value, "value");
      String var4 = thisRef + " 的 " + property.getName() + " 属性赋值为 " + value;
      System.out.println(var4);
   }
}

public final class A {
   // $FF: synthetic field
  //虽然实际上我也不知道这个是啥意思,但是能大概猜出来啥意思,用于反射和属性定义,毕竟这个类实际上是没有 name:String 属性的
   static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty1(new MutablePropertyReference1Impl(Reflection.getOrCreateKotlinClass(A.class), "name", "getName()Ljava/lang/String;"))};
   //真正的类型是 Delegate的类型
   private final Delegate name$delegate = new Delegate();
   // get set 方法 是 String 类型
   private final String getName() {
     //调用委托的 getValue 方法
      return this.name$delegate.getValue(this, $$delegatedProperties[0]);
   }

   private final void setName(String var1) {
      this.name$delegate.setValue(this, $$delegatedProperties[0], var1);
   }
}

yizems avatar Aug 02 '19 02:08 yizems

属性委托

有些常见的属性操作,我们可以通过委托方式,让它实现,例如:

  • lazy 延迟属性: 值只在第一次访问的时候计算
  • observable 可观察属性:属性发生改变时通知
  • map 集合: 将属性存在一个map集合里面

类委托

可以通过类委托来减少 extend 类委托的时,编译器回优使用自身重新函数,而不是委托对象的函数


interface Base{
fun print()
}

case BaseImpl(var x: Int):Base{

override fun print(){
print(x)
}

}
// Derived 的 print 实现会通过构造函数的b对象来完成
class Derived(b: base): Base by b

MicroKibaco avatar Aug 03 '19 07:08 MicroKibaco

类委托: class A: Base by BaseImp()  实现一个接口了正好有一个类可以使用

属性委托:委托的类需要实现 getValue和setValue 函数加上operator关键字

委托延迟: by lazy  ,lazy内只执行一次,后续只返回结果

委托工厂:主要需要实现ReadWriteProperty 接口

属性监听: Delegates.observable 无条件赋值 和Delegates.vetoable (有条件的赋值)

lix-b avatar Apr 03 '21 01:04 lix-b

https://book.kotlincn.net/text/delegated-properties.html

yihu5566 avatar Jul 07 '22 08:07 yihu5566

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

MicroKibaco avatar Jul 07 '22 08:07 MicroKibaco