2

I am writing a new app and I have chosen to use Java for flexibility. It is a GUI app so I will use JavaFX. This is my first time using Java but I have experience with C#.

I am getting familiar with JavaFX Properties, they look like a great way of bi-directional binding between front-end and back-end.

My code uses classes from an open-source API, and I would like to convert the members of these classes to JavaFX Properties (String => StringProperty, etc). I believe this would be transparent to any objects that refer to these members.

Is it ok to do this? Is it the suggested way of dealing with existing classes? What do I do about Enum types? E.g. an enum member has it's value changed, how should I connect the enum member to the front-end?

Thank you :)

mils
  • 1,878
  • 2
  • 21
  • 42

1 Answers1

5

In general, as long as you don't change the public API of the class - in other words you don't remove any public methods, modify their parameter types or return types, or change their functionality - you should not break any code that uses them.

So, e.g. a change from

public class Foo {

    private String bar ;

    public String getBar() {
        return bar ;
    }

    public void setBar(String bar) {
        this.bar = bar ;
    }
}

to

public class Foo {
    private final StringProperty bar = new SimpleStringProperty();

    public StringProperty barProperty() {
        return bar ;
    }

    public String getBar() {
        return barProperty().get();
    }

    public void setBar(String bar) {
        barProperty().set(bar);
    }
}

should not break any clients of the class Foo. The only possible problem is that classes that have subclassed Foo and overridden getBar() and/or setBar(...) might get unexpected behavior if their superclass is replaced with the new implementation (specifically, if getBar() and setBar(...) are not final, you have no way to enforce that getBar()==barProperty().get(), which is desirable).

For enums (and other objects) you can use an ObjectProperty<>:

Given

public enum Option { FIRST_CHOICE, SECOND_CHOICE, THIRD_CHOICE }

Then you can do

public class Foo {

    private final ObjectProperty<Option> option = new SimpleObjectProperty<>();

    public ObjectProperty<Option> optionProperty() {
         return option ;
    }

    public Option getOption() {
        return optionProperty().get();
    }

    public void setOption(Option choice) {
        optionProperty().set(choice);
    }
}

One caveat to all this is that you do introduce a dependency on the JavaFX API that wasn't previously present in these classes. JavaFX ships with the Oracle JDK, but it is not a full part of the JSE (e.g. it is not included in OpenJDK by default, and not included in some other JSE implementations). So in practice, you're highly unlikely to be able to persuade the developers of the open source library to accept your changes to the classes in the library. Since it's open source, you can of course maintain your own fork of the library with JavaFX properties, but then it will get tricky if you want to incorporate new versions of that library (you will need to merge two different sets of changes, essentially).

Another option is to use bound properties in the classes, and wrap them using a Java Bean Property Adapter. This is described in this question.

Community
  • 1
  • 1
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Sir, if you are ever in Sydney I shall buy you a cookie. A follow on question regarding the above - I read the question you linked to, and so it appears that my options are: 1) To replace the API types with properties 2) To implement property change listeners in the API. Is there a way to implement either of these via inheritance, so that I extend the base API class, as opposed to editing it directly? Again, thank you for your detailed answer. – mils Feb 05 '16 at 23:21