2014-04-08 26 views
1

看来,有两种情况,其中分配到通过@Bindable一个结合常规属性不调用监听器:例外Groovy的绑定/ vetoable属性更改侦听

(1)在其中该属性内进行分配的情况下类本身,如this.prop = newval,或者简单地说,prop = newval

(2)的情况下属性的值不会改变obj.prop = oldval

有没有办法解决?理想情况下,它将支持简单的(.)prop=语法。

代码示例:

import java.beans.* 
import groovy.beans.* 

int changes = 0 
def obj = Binding.newInstance() 
obj.propertyChange = { changes++ } 
obj.prop = "1st change" // change recorded 
obj.twoChanges()   // no changes recorded 
obj.prop = obj.prop  // no change recorded 
assert changes == 4  // fails: changes is 1 

class Binding { 
    @Bindable String prop 
    def twoChanges() { 
    prop = "2nd change" 
    this.prop = "3rd change" 
    } 
} 
+0

你可以提供一个示例代码:除非该属性设置为相同的值(3出检测到4种变化),这适用于一切? – Opal

回答

2

通过创建一个隐藏的@Bindable属性(mprop),并没有一个名为prop实际属性提供只针对prop一个getter和setter,我可以用你的语法不变。

import java.beans.* 
import groovy.beans.* 

int changes = 0 
def obj = Binding.newInstance() 
obj.propertyChange = { changes++ } 
obj.prop = "1st change" // change recorded 
obj.twoChanges()   // two changes recorded 
obj.prop = obj.prop  // no change recorded 
assert changes == 4  // fails: changes is 3 


class Binding { 
    @Bindable String mprop   // changed from prop to mprop 
    def setProp(x) {setMprop(x)}  // new setter 
    def getProp() {getMprop()}  // new getter 
    def twoChanges() { 
    prop = "2nd change" 
    this.prop = "3rd change" 
    } 
} 
1

对于(1),@Bindable是产生,除其他的东西,自定义制定者的AST,当你访问类中的属性,它不通过走二传手。这工作:

import java.beans.* 
import groovy.beans.* 

int changes = 0 
def obj = Binding.newInstance() 
obj.propertyChange = { changes++ } 
obj.prop = "1st change" // change recorded 
obj.twoChanges()   // no changes recorded 
obj.prop = obj.prop  // no change recorded 
assert changes == 3  // fails: changes is 1 

class Binding { 
    @Bindable String prop 
    def twoChanges() { 
    setProp("2nd change") 
    this.setProp("3rd change" ) 
    } 
} 

对于(2),好了,这似乎是PropertyChangeListenerstandard behavior,因为属性没有改变。也许你可以提供一个custom object, with a custom equals,或者只是创建一个自定义setter。

+0

(1):我可以在我想的类中使用'[]'',或者只是使用'set()'并强制所有的集合通过它。在这个例子中,有很多代码需要直接设置值。 (2):这是一个有趣的想法。在这种情况下,属性是原语,我认为这里提出的是自定义类属性,除非我读错了,这是可能的。在这一点上,我正在考虑编写自己的'@ Editable',它可能会在隐藏数据属性($ prop)周围生成访问器。 “@ Bindable”代码是公开的吗?我似乎无法找到它。 – inyourcorner

+0

我在groovy-all jar中发现了这个实现。 – inyourcorner

0

下面是我最终做到的,而不需要使用@Bindable。我愿意接受建议,特别是this.with {}

class Obj { 
    int val = 0 
    static int numCalls = 0 
    List assigns = [] 

    void setProperty(String name, Object value) { 
    [email protected]"$name" = value 
    assigns << [name: value] 
    numCalls ++ 
    } 

    int nop() { 
    this.with { 
     val = val 
    } 
    } 

    int inc() { 
    this.with { 
     this.val += 1 
    } 
    return this.val 
    } 

} 

def obj = Obj.newInstance() 
assert obj.val == 0 && Obj.numCalls == 0 
assert obj.inc() == 1 && obj.val == 1 && Obj.numCalls == 1 
assert obj.nop() == 1 && obj.val == 1 && Obj.numCalls == 2 && obj.assigns.size() == 2 
+0

我正面临同样的问题。我并不在乎在不改变其价值的情况下触摸领域,但我想强制使用二传手,即使是在课堂内部也是如此。你有没有找到比这更好的解决方案?{}? – greymatter

+0

不,我们无法找到另一种方式,所以我们解决了这个问题。 – inyourcorner

+0

1月6日你有看到我的答案吗?我正在使用这种方法,它完美地工作。 – greymatter