【问题标题】:When to use JavaFX properties setter and getter, instead of using the property directly何时使用 JavaFX 属性 setter 和 getter,而不是直接使用属性
【发布时间】:2015-11-20 19:04:30
【问题描述】:

我熟悉Java,但刚开始学习JavaFX,特别是学习JavaFX属性。我了解 Oracle 的以下示例所示的基本设计模式:

package propertydemo;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;

class Bill {

    // Define a variable to store the property
    private DoubleProperty amountDue = new SimpleDoubleProperty();

    // Define a getter for the property's value
    public final double getAmountDue(){return amountDue.get();}

    // Define a setter for the property's value
    public final void setAmountDue(double value){amountDue.set(value);}

     // Define a getter for the property itself
    public DoubleProperty amountDueProperty() {return amountDue;}

}

我不明白什么时候/为什么要使用 getter 和 setter 方法,而不是直接使用 Property?

我的想法是,您可能希望在 getter 和/或 setter 中使用一些自定义代码,这些代码可能会对数据进行一些前后操作/验证,但如果您创建自定义 getter 和/或 setter,您会然后得到不同的结果,具体取决于您是直接使用 getter/setter 还是属性,这对我来说似乎很危险。

如果 getter/setter 只是调用 Property 的 get 和 set 方法,那为什么还要有它们呢?

对此的任何见解将不胜感激。

【问题讨论】:

  • 来自learn javafx ebook 。 Additional getters and setters, using JavaBeans naming convention, are added to make the class interoperable with the older tools and frameworks that use the old JavaBeans naming conventions to identify the properties of a class.
  • 在我看来,不需要额外的 getter 和 setter。
  • @Kachna 这当然取决于您的用例。例如,如果您想在 JPA 实体中使用 JavaFX 属性,则需要 get 和 set 方法。同样,如果您使用 JSON 或 XML 编组等。

标签: java javafx properties setter getter


【解决方案1】:

JavaFX 属性模式旨在扩展旧的标准 JavaBean 模式。因此,在您的示例中,根据 JavaBean 约定,您有一个类型为double 的(读写)属性,称为amount。这是由两种方法决定的

public double getAmount() ;
public void setAmount(double amount);

JavaBean 模式通过“绑定属性”允许一些有限的“可观察性”,其中 bean 支持注册PropertyChangeListener。 UI 工具包通常需要观察属性并响应更改。例如,Label 具有 text 属性是有意义的。如果text 属性发生更改,则需要通知Label,以便它知道重新绘制自己。乍一看,使用带有绑定属性的 JavaBean 是一种方法。但是,在 UI 工具包中使用这种机制会产生性能问题,因为如果不立即计算值,就无法通知该值不再有效。这意味着,例如,每次对属性进行单独更改时都会重新计算布局。

JavaFX 团队的目标显然是定义一个模式

  1. 符合标准 JavaBean 模式,并且
  2. 支持的可观察属性可以跟踪失效,而无需在每次值更改时重新计算相关值(“惰性可观察值”)

因此,JavaFX 解决方案是创建同时支持ChangeListeners 和InvalidationListeners(当值更改时通知)和InvalidationListeners(当值不再有效时通知)的属性。这意味着,例如,布局机制可以跟踪它当前是否有效,而无需在它变为无效时强制重新计算。布局只会在实际屏幕脉冲(即渲染场景时)上重新计算,并且只有在它无效时才会重新计算。

(作为一个快速的概念验证,请考虑以下几点:

DoubleProperty width = new SimpleDoubleProperty(3);
DoubleProperty height = new SimpleDoubleProperty(4);
ObservableDoubleValue area = Bindings.createDoubleBinding(() -> {
    double a = width.get() * height.get();
    System.out.println("Computed area: "+a);
    return a ;
}, width, height);
System.out.println("Area is "+area.getValue());
width.set(2);
height.set(3);
System.out.println("Area is "+area.getValue());

请注意,当width 为 2 而height 仍为 4 时,永远不会计算中间值。)

因此,JavaFX 中的值由这些可观察的 Properties 表示,它们同时支持失效侦听器和更改侦听器,这意味着它们基本上是“可延迟观察的”。通过属性访问器方法(在您的示例中为amountProperty())公开属性本身就足以支持此功能。

然而,从语义上讲,暴露DoubleProperty 意味着该bean 具有double 类型的值。为了保持与旧 JavaBean 约定的兼容性,该 bean 应该通过公开相应的 get 和 set 方法来宣传这一事实。因此,JavaFX 属性模式需要“属性访问器”(amountProperty())以及标准的 JavaBean 方法(getAmount() 和 setAmount(...))。这意味着遵循 JavaFX 模式的 bean 可以在任何使用标准 JavaBean 模式的地方使用,例如JPA。

请注意,要使模式正常工作,amountProperty().get() == getAmount() 和amountProperty().set(x) 与setAmount(x) 具有相同的效果应该始终为 true。这可以通过将get 和set 方法设为final 来保证(即使bean 类是子类),如您的示例所示。

如果您自己调用方法来检索或更改属性的值,则调用哪个方法并不重要,因为它们保证具有相同的效果。由于 JavaFX 属性模式是 JavaBean 模式的扩展,因此调用 get 和 set 方法可能会稍有偏好:从某种意义上说,访问值只需要 JavaBean 功能,而不需要完整的 JavaFX 属性功能,因此仅依赖该功能可能具有某种语义意义。然而,在实践中,你使用哪一个并没有什么区别。

【讨论】:

  • 感谢您的详细解释。 setter 实际操作数据的情况如何,例如,如果您有一个 StringProperty firstName:firstName.set(name.trim()) 在这种情况下,调用 setter 方法与在属性上调用 set() 不同,或者这是一个禁忌JavaFX 属性。
  • 对不起,我想添加一个更详细的示例,但您似乎无法将代码块添加到 cmets。
  • 您将通过该示例打破多个约定。如前所述,在 JavaFX 属性模式中,您应该保证 setFirstName(x) 等价于 firstNameProperty().set(x)。但在常规 Java Bean 模式中,您应该真正保证 setFirstName(x); getFirstName() 的计算结果为 x,假设在两个方法调用之间对象上没有发生其他操作。如果你真的想做这样的事情,继承 StringPropertyBase 并覆盖 setString(...) 和 setValue(String)。
  • @James_D,你的意思是覆盖 set(String) 和 String get() 吗?特别是,StringPropertyBase 似乎没有 setString 方法。
猜你喜欢
  • 2017-10-09
  • 2010-11-16
  • 2021-10-22
  • 2017-04-13
  • 2016-12-21
  • 2010-09-09
  • 1970-01-01
  • 2011-09-07
  • 1970-01-01
相关资源
最近更新 更多