1

似乎有两种情况下分配给绑定的 groovy 属性 through@Bindable不会调用侦听器:

(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"
  }
}
4

3 回答 3

2

通过创建一个隐藏@Bindable属性 ( mprop) 并仅提供一个 getter 和 setter ,prop而没有一个名为 的实际属性prop,我能够使用您的语法不变。这适用于除属性设置为相同值(检测到 4 个更改中的 3 个)之外的所有内容:

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"
  }
}
于 2015-01-05T03:59:04.803 回答
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),好吧,这似乎是 的标准行为PropertyChangeListener因为属性没有改变。也许你可以提供一个自定义对象,一个自定义的 equals,或者只是创建一个自定义设置器。

于 2014-04-08T16:49:16.550 回答
0

这就是我最终的做法,无需使用@Bindable。我愿意接受建议,尤其是this.with {}.

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

  void setProperty(String name, Object value) {
    this.@"$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
于 2014-04-11T13:32:43.613 回答