You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Kotlin扩展属性实现交替返回true/false的布尔属性

Kotlin扩展属性实现交替布尔值的方案

问题背景

需要给对象添加一个布尔属性,行为要求:

  • 首次获取返回true
  • 第二次获取返回false
  • 后续每次调用交替返回(偶数次调用返回true,奇数次返回false)

通过类属性可以轻松实现该逻辑:

class Foo {
    var bar: Boolean = true
        get() {
            val value = field
            bar = value.not()
            return value
        }
        private set
}

但尝试用扩展属性实现时出现报错:

var Foo.bar: Boolean = true // 报错:extension property cannot be initialized because it has no backing field
    get() {
        val value = field // 报错:Unresolved reference field
        bar = value.not()
        return value
    }
    private set

报错核心原因:Kotlin扩展属性本质是静态方法的语法糖,不会给原类添加实际成员变量,因此没有自带的 backing field,无法直接用field关键字访问或初始化值。

可行实现方案(Kotlin 1.8.0,Android环境)

方案1:用WeakHashMap维护状态(通用场景)

利用WeakHashMap存储每个对象的状态,它的键是弱引用,不会阻止对象被垃圾回收,能有效避免内存泄漏:

// 全局容器,维护每个Foo实例的布尔状态
private val barState = WeakHashMap<Foo, Boolean>()

var Foo.bar: Boolean
    get() {
        // 首次获取默认返回true,后续读取存储的状态
        val currentValue = barState.getOrDefault(this, true)
        // 切换状态并存回容器
        barState[this] = !currentValue
        return currentValue
    }
    private set(value) {
        barState[this] = value
    }

方案2:用View的Tag存储(仅适用于View子类)

如果Foo是Android的View子类,可以利用系统自带的Tag机制存储状态:

  1. 先在res/values/ids.xml中定义唯一ID:
<item name="bar_state_tag" type="id"/>
  1. 实现扩展属性:
var Foo.bar: Boolean
    get() {
        val currentValue = getTag(R.id.bar_state_tag) as? Boolean ?: true
        setTag(R.id.bar_state_tag, !currentValue)
        return currentValue
    }
    private set(value) {
        setTag(R.id.bar_state_tag, value)
    }

原理说明

Kotlin扩展属性不会修改原类的结构,只是提供了静态方法的语法糖包装。要实现带状态的扩展属性,必须通过外部容器(如WeakHashMap、View Tag)为每个实例单独维护状态,以此模拟类属性的backing field功能。

内容的提问来源于stack exchange,提问作者Leonardo Sibela

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 06:42:49