在 Kotlin 中,by :: 是一种属性间委托的语法糖,用于直接将一个属性的读写操作委托给另一个已存在的属性。通过这种机制,两个属性将共享同一份数据存储空间,操作任一属性会同步影响另一方。
委托类 委托的是接口的方法
委托属性 委托的是属性的set get
一、语法解析
示例代码:
var number: Float by ::floatValue
- **
floatValue**:被委托的已有属性(需与number同属一个类或作用域)。 -
::操作符:表示委托关系,系统会自动生成getValue和setValue逻辑,无需手动实现委托类7。
二、核心特性
| 特性 | 说明 |
|---|---|
| 数据共享 | 委托方(number)与被委托方(floatValue)共享同一数据源,修改一方会同步另一方7。 |
| 简化代码 | 避免重复定义存储逻辑,适用于需要多属性映射同一底层数据的场景(如别名属性)78。 |
| 内置实现 | 基于 Kotlin 标准库的 PropertyDelegateProvider 自动处理委托逻辑,无需自定义委托类7。 |
三、代码示例
class Simple04 {
// var 可读 可改 内部会有 set get val 只有get 只读
var floatValue : Float = 757567.65f
set(v) {
field = v
println("你设置了 floatValue哦 v:$v")
}
get() {
println("你获取了 floatValue哦")
return field
}
var number : Float by ::floatValue
/*set(v) { 相当于,隐式的有这段代码哦
field = v
println("你设置了floatValue哦 v:$v")
}
get() {
println("你获取了floatValue哦")
return field
}*/
/*
背后实现的原理:是通过单例来实现的
public final class Simple04 {
// 实例 方便访问 getFloatValue setFloatValue 的实例
private final KMutableProperty0 number$delegate = new Simple04$number$2((Simple04)this);
private float floatValue = 8768979.0F;
public final float getFloatValue() {
String var1 = "你获取了floatValue哦";
System.out.println(var1);
return this.floatValue;
}
public final void setFloatValue(float v) {
this.floatValue = v;
String var2 = "你设置了floatValue哦 v:" + v;
System.out.println(var2);
}
// 用户在读取 number 调用 getNumber ---> 实例 ---> getFloatValue
public final float getNumber() {
KProperty0 var1 = (KProperty0)this.number$delegate;
Object var3 = null;
return ((Number)var1.get()).floatValue();
}
// 用户在赋值 number 调用 setNumber ---> 实例 ---> setFloatValue
public final void setNumber(float var1) {
KMutableProperty0 var2 = this.number$delegate;
Object var4 = null;
Float var5 = var1;
var2.set(var5);
}
}
*/
}
fun main() {
val simple04 = Simple04()
simple04.number = 99999.0f // 我给number赋值【用户在赋值 number 调用 setNumber ---> 实例 ---> setFloatValue】
println(simple04.number) // 我读取number【/用户在读取 number 调用 getNumber ---> 实例 ---> getFloatValue】
}
- 输出结果:
你获取了 floatValue哦
757567.6
四、应用场景
- 属性别名
为已有属性提供更直观的命名(如width委托给size.width)。 - 数据同步
多个属性需要实时同步同一数据源时(如 UI 控件与数据模型绑定)。 - 代码精简
替代显式委托类的模板代码,简化逻辑重复场景的实现。
五、注意事项
- 作用域限制
被委托属性(如floatValue)需与委托属性(如number)在同一类或作用域内。 - 类型一致性
委托属性和被委托属性的类型必须兼容(相同类型或其父类)6。 - 仅限
var属性
by ::语法要求委托属性必须是可变属性(var),不可用于val。
通过 by ::,Kotlin 提供了一种简洁高效的方式实现属性间的数据共享与逻辑复用,适用于需要简化属性映射关系的场景78。