JavaFX属性:重写getBean()方法?

Jai*_*Jai 1 java javafx javafx-8

Javadoc ReadOnlyProperty.getBean()表示:

对象getBean()

返回包含此属性的对象。如果此属性未包含在Object中,则返回null。

我注意到,在许多节点中,大多数(如果不是全部)属性都被定义getBean()为覆盖该方法。当然,考虑getBean()到Javadoc中对Java语言的描述,这样做非常有意义。

但是,大多数人(例如您和我)可能会这样做:

ObjectProperty<MyClass> myObj = new SimpleObjectProperty<>();
Run Code Online (Sandbox Code Playgroud)

我们没有覆盖该getBean()方法,没有它,一切似乎都可以工作。那么,是否有一些我们不能通过覆盖而错过的东西getBean()

我已经看到了Javadoc给出的许多覆盖此方法的示例。例如,来自PseudoClass Javadoc:

public boolean isMagic() {
    return magic.get();
}

public BooleanProperty magicProperty() {
    return magic;
}

public BooleanProperty magic =
    new BooleanPropertyBase(false) {

    @Override protected void invalidated() {
        pseudoClassStateChanged(MAGIC_PSEUDO_CLASS. get());
    }

    @Override public Object getBean() {
        return MyControl.this;
    }

    @Override public String getName() {
        return "magic";
    }
};

private static final PseudoClass MAGIC_PSEUDO_CLASS = PseudoClass.getPseudoClass("xyzzy");
Run Code Online (Sandbox Code Playgroud)

我们大多数人甚至都不会使用抽象基类实例化属性(而且很可能甚至不熟悉)。为什么该示例将以这种方式而不是简单地这样做:

public boolean isMagic() {
    return magic.get();
}

public BooleanProperty magicProperty() {
    return magic;
}

public BooleanProperty magic =
    new SimpleBooleanPropertyBase(false) {

    @Override protected void invalidated() {
        super.invalidated();
        pseudoClassStateChanged(MAGIC_PSEUDO_CLASS. get());
    }
};

private static final PseudoClass MAGIC_PSEUDO_CLASS = PseudoClass.getPseudoClass("xyzzy");
Run Code Online (Sandbox Code Playgroud)

或更常见的方法是将无效侦听器添加到BooleanProperty

public BooleanProperty magic = new BooleanPropertyBase(false);
magic.addListener(observable -> pseudoClassStateChanged(MAGIC_PSEUDO_CLASS. magic.get());
Run Code Online (Sandbox Code Playgroud)

Javadoc的编写方式表明这是正确的方法。如果您偏离了此做法,则可能操作不正确,并且可能无法获得预期的结果。

所以,这些是我的问题:

  1. 我们需要覆盖getBean()吗?
  2. 在什么条件下我们需要或应该覆盖它?
  3. 是否有任何条件我们不能覆盖它?

小智 5

tl; dr

  1. 您不必重写getBean()。
  2. 如果需要信息,则应覆盖它。
  3. 我不知道有任何条件,您不能在该条件下覆盖它。

属性“ bean”是有关属性的元信息,并且是可选的。(属性btw的“名称”也一样。)无论是否指定名称和拥有的bean,属性的核心功能(获取和设置值,绑定,侦听器)都可以使用。

但是您可能希望在应用程序代码中使用此信息。例如,如果您重复使用侦听器,则可以使用此信息来标识事件的来源。通用库和工具也可以使用此信息。例如,ScenicView可以使用bean和name来构建(尽管我不知道它是如何实现的)。

不必重写抽象基类。所有SimpleProperty类都具有允许您设置名称和bean的构造函数。

大多数内部属性会覆盖抽象基类而不是实例化SimpleProperty的原因是较小的内存占用。如果您在少数几个对象中只有几个属性,那就没关系了,因为您只保存了几个字节。但是,如果您在成百上千个节点中拥有数十个属性,并且尝试在有限的设备上运行,那么类似的事情就变得很重要。出于相同的原因,内部属性会覆盖invalidated()而不是附加侦听器。