kuhaku kuhaku - 3 months ago 13
Java Question

Exposing properties for binding

How should properties be exposed?

For example:

class A{
private ObjectProperty<X> objx;
}

class B{
private ObjectProperty<X> objy;
}


We want to bind
objy
to
objx
or add a listener to
objx
from
B
. Is it fine to just make a getter for
objx
? or is there a way to make a wrapper function for binding and expose just this function?

Answer

The standard pattern is

class A {
    private final ObjectProperty<X> objx = new SimpleObjectProperty<>();

    public ObjectProperty<X> objxProperty() {
        return objx ;
    }

    public final X getObjx() {
        return objxProperty().get();
    }

    public final void setObjx(X objx) {
        objxProperty().set(objx);
    }
}

The idea here is that you have an accessor method for the property itself (a "property accessor": objxProperty()) which can be used for binding and registering listeners, but the property also appears as a regular Java Bean as well: i.e. there are standard get and set methods. The general contract is that you should always have x.getObjx() == x.objxProperty().get(), which is enforced by making the Java Bean accessor methods (getObjx() and setObjx) final.

If you want to be able to modify the property internally, but want to only expose a read only property (to which other code could bind) use a ReadOnlyObjectWrapper:

class A {

    private final ReadOnlyObjectWrapper<X> objx = new ReadOnlyObjectWrapper<>();

    public ReadOnlyObjectProperty<X> objxProperty() {
        return objx.getReadOnlyProperty();
    }

    public final X getObjx() {
        return objxProperty().get();
    }

}

Also have a look at this powerpoint presentation which, while old, shows a lot of useful idioms such as lazy- and super-lazy- initialization of the property.