Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Moosphan opened this issue Jul 26, 2019 · 6 comments
Labels

Comments

@Moosphan
Copy link
Owner

No description provided.

@18361237136
Copy link

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

@yizems
Copy link

yizems commented Aug 2, 2019

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

  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);
   }
}

@MicroKibaco
Copy link

属性委托

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

  • 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

@lix-b
Copy link

lix-b commented Apr 3, 2021

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

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

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

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

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

@yihu5566
Copy link

yihu5566 commented Jul 7, 2022

@MicroKibaco
Copy link

MicroKibaco commented Jul 7, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants