首页 > 解决方案 > 是否可以在 Groovy 中监听超类属性的变化?

问题描述

我想为一个属性创建一个“重新加载”设置器,我想保留一个特性。然后任何实现 trait 的子类都将使用它们自己的 getter,但使用 trait 的 setter。我不想为现有属性添加任何额外的注释。这里有一个澄清:

trait Tr {
    abstract String getS()
    void setS(String value) {
        ((GroovyObject) this).setProperty('s', value)
        reloadOnSChange()
    }

    void reloadOnSChange() {
        // do something when S is changed
    }
}

class Cl implements Tr {
    String s
}

Cl cl = new Cl()
cl.s = 'hello world' // reloadOnSChange should be called

这样的属性监听器可能吗?

标签: groovy

解决方案


如果你想为此使用 trait,那么你必须与实现void getS(String value)方法不同,因为 Groovy 编译器生成Cl.getS(String value)的方法会隐藏在Trtrait 中实现的方法。

或者,您的 trait 可以提供void setProperty(String name, Object value)方法的实现,如果调用 property s,它会执行reloadOnSChange()方法。考虑以下示例:

trait Tr {
    abstract String getS()
    abstract void setS(String s)

    void reloadOnSChange() {
        // do something when S is changed
        println "RELOAD"
    }

    void setProperty(String name, Object value) {
        metaClass.setProperty(this, name, value)
        if (name == 's') {
            reloadOnSChange()
        }
    }
}

class Cl implements Tr {
    String s
}

Cl cl = new Cl()
cl.s = 'hello world'

println "Dump: ${cl.dump()}"

输出:

RELOAD
Dump: <Cl@6580cfdd s=hello world>

主要缺点是该setProperty方法将对每个属性执行,因此可能会产生一些开销。在某些时候,JIT 应该优化代码并确保if仅当属性名称等于时才执行此语句s


推荐阅读