是否可以在Groovy中侦听超类属性的变化?

时间:2018-09-21 14:27:27

标签: groovy

我想为一个属性创建一个“重载”设置器,并希望保留该特征。然后,实现该特性的所有子类都将使用其自己的getter,但使用该特性的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

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

1 个答案:

答案 0 :(得分:1)

如果要为此使用特征,则必须与实现void getS(String value)方法不同,因为Groovy编译器会生成Cl.getS(String value)方法,该方法会遮盖以Tr特征实现的方法

或者,您的特征可以提供void setProperty(String name, Object value)方法的实现,如果对属性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语句。