Kotlin属性Setter重载:为何无法用赋值语法调用Int参数Setter?
解决Kotlin中Long属性支持Int/Long赋值语法的问题
问题根源在于:Kotlin的属性赋值语法myNumber = 4会自动把Int转成Long,直接调用属性默认生成的setMyNumber(Long)方法,不会触发你自定义的setMyNumber(Int)函数——Kotlin会优先匹配属性的setter,而非同名的普通函数。
下面是两种能保留赋值语法的解决方案:
方法1:使用委托属性(推荐)
自定义一个委托类,重载不同类型的setValue方法,让赋值语法自动匹配对应的类型处理逻辑:
import kotlin.reflect.KProperty class LongProperty { private var backingValue: Long = 0L // 处理Long类型的读取和赋值 operator fun getValue(thisRef: Any?, property: KProperty<*>): Long = backingValue operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { backingValue = value // 这里可添加Long类型赋值的自定义逻辑,比如参数校验、日志打印 } // 处理Int类型的赋值 operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { backingValue = value.toLong() // 这里添加Int类型赋值的自定义逻辑 } } class MyClass { var myNumber by LongProperty() } // 测试示例 fun main() { val obj = MyClass() obj.myNumber = 4 // 触发Int类型的setValue逻辑 obj.myNumber = 5L // 触发Long类型的setValue逻辑 println(obj.myNumber) // 输出5 }
方法2:私有化默认setter+扩展赋值运算符
如果不想用委托,也可以把属性的默认setter设为私有,配合重载函数和扩展运算符实现需求:
class MyClass { var myNumber: Long = 0L private set // 私有化默认setter,禁止外部直接调用 // 处理Long类型赋值 fun setMyNumber(value: Long) { field = value // Long类型的自定义逻辑 } // 处理Int类型赋值 fun setMyNumber(value: Int) { field = value.toLong() // Int类型的自定义逻辑 } } // 扩展赋值运算符,让Int类型可以用赋值语法调用 operator fun MyClass.setMyNumber(value: Int) { this.setMyNumber(value) } // 测试示例 fun main() { val obj = MyClass() obj.myNumber = 4 // 实际调用自定义的setMyNumber(Int) obj.myNumber = 6L // 实际调用setMyNumber(Long) }
两种方案都能保留myNumber = 数值的赋值语法,同时根据赋值类型触发对应逻辑,Java代码也依然可以正常调用两个重载的setMyNumber方法。
内容的提问来源于stack exchange,提问作者Gunnar Bernstein
相关产品推荐
相关产品推荐

