groovy'的例外情况;s可绑定/可否决属性更改侦听器

groovy'的例外情况;s可绑定/可否决属性更改侦听器,groovy,bindable,Groovy,Bindable,在两种情况下,通过@Bindable对绑定groovy属性的赋值不会调用侦听器: (1) 在属性在类本身内赋值的情况下,例如this.prop=newval,或者简单地说,prop=newval (2) 在属性值不变的情况下,obj.prop=oldval 有办法解决这个问题吗?理想情况下,它将支持简单的(.)prop=语法 代码示例: import java.beans.* import groovy.beans.* int changes = 0 def obj = Binding.new

在两种情况下,通过
@Bindable
对绑定groovy属性的赋值不会调用侦听器:

(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"
  }
}
For(1)是一个AST,它生成自定义setter,当您访问类内的属性时,它不经过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()          // 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
,因为属性没有更改。也许你可以提供一个,或者只是创建一个自定义setter。

下面是我如何完成的,而不需要使用@Bindable。我愿意接受建议,尤其是
这个.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
类Obj{
int val=0
静态int numCalls=0
列表分配=[]
void setProperty(字符串名称、对象值){
此。@“$name”=值

通过创建一个隐藏的
@Bindable
属性(
mprop
),并且只为
prop
提供一个getter和setter,而没有一个名为
prop
的实际属性,分配,我可以使用您的语法不变。这适用于所有情况,除非属性设置为相同的值(检测到4次更改中的3次):


你能提供一个示例代码吗?(1):我可以在我猜的类中使用
[]
s,或者只需要一个
set()
并强制所有set都通过它。问题是,在示例中,编写的许多代码都希望直接设置值。(2):这是一个有趣的想法。在这种情况下,属性是原语,我认为这里建议的是自定义类属性,除非我读错了,这是可能的。此时,我正在考虑编写我自己的
@Editable
,它将围绕隐藏的数据属性($prop)生成访问器也许吧。
@Bindable
代码是公共的吗?我似乎找不到它。我在groovy all jar中找到了正确的实现。我面临着同样的问题。我不太在乎在不更改字段值的情况下触摸字段,但我想强制使用setter,即使是从类内部。你有没有找到比这个更好的解决方案是的。有{}吗?不,我们找不到另一种方法,所以我们解决了这个问题。你看到我1月6日的答案了吗?我用的是这个方法,效果非常好。
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"
  }
}