我在 javafx 中编写了一个类,其中有两个双向绑定的属性,并且正在测试一些边缘情况。我发现,如果您从无效侦听器内部更改其中一个属性的值,则会导致属性不同步。这是一个小例子:
static class A {
IntegerProperty x = new SimpleIntegerProperty(this, "x", 0);
IntegerProperty y = new SimpleIntegerProperty(this, "y", 0);
A() {
x.bindBidirectional(y);
}
}
static void testA() {
A a = new A();
a.x.addListener( o -> { //InvalidationListener
if (a.x.get() < 0) a.x.set(0);
});
// after y is set to a negative value, x and y hold different values
// until either y is set to a value that's >= 0 or x is set to any value
a.y.set(-2);
System.out.println(a.x.get());
System.out.println(a.y.get());
}
输出:
0
-2
我假设使用双向绑定时,更改一个属性总是会导致另一个属性更新。编写这样的无效侦听器似乎很少见(并且可能不明智),但我在这里是出于防御考虑。如果至少有一个这些属性被暴露,我不希望它有可能破坏我的类的任何不变量。我认为这里有三种可能的解释:
双向绑定的约定并不是它们始终保持同步(要么它们保持相同的值,要么它们被标记为无效),而只是基于尽力而为。因此,类不变量不应基于这一事实。
更改失效侦听器中的值会破坏双向绑定的前提条件,应避免这样做。否则它们始终保持同步。因此,您可以根据这一事实制定类不变量,因为要求客户端不应编写这样的失效侦听器是合理的。
这是一个错误,无论如何它们实际上应该是同步的。我猜如果这是真的,那么你很容易产生无限循环的更改通知(比如向 y 添加一个始终将值设置为 < 0 的无效侦听器)。因此,由客户端来防止这种情况发生。
这些解释中是否有任何接近事实的解释,或者我是否遗漏了其他内容?另外,我很想知道是否存在其他类型的绑定操作可以考虑到这些情况。