- A getter method.
- A setter method.
- A listener / notification mechanism for when the property changes.
The key problem with the ad-hoc implementation of properties (as in JavaBeans) is that they tend to make classes noisy, with all of the
getX(), setX() stuff, and the listener mechanism. Things become even more complicated when properties take on the nature of collections, where multiple objects can conceptually be added or removed.In a search for simplicity, I have been investigating JavaFX and the even more impressive ScalaFX. However, JavaFX does not yet allow bindings to properties implemented in a Java model, and ScalaFX, although very promising, is not quite ready for prime time. (It's more the potential for bugs I can't understand rather than API changes that have put me off ScalaFX for the time being.)
Until ScalaFX is ready, I have found a neat stop-gap solution. Inspired by the Scala wiki entry on Properties, I have set up my own properties as follows:
My Properties extend
scala.swing.Publisher so it's possible to listenTo them for events. I defined a PropertyChanged event that is intended to be fired when a property changes. The properties also have apply() and update() methods which act as getters and setters respectively.So, what advantages do these kinds of properties have over normal
getX(), setX() and a listener mechanism?Firstly, the contract of a property is clearly defined. There is no bean-like assumption that a
setX() method on a class is related to a corresponding getX() method, nor that a particular event will be fired when a change occurs.Secondly, each property is nicely modularized. Properties often refer directly to a value stored in a class, and it's easy to define a
ValueProperty which performs this automatically. Then, for the enclosing class, you can write something like this:Instead of something like this:
At first glance, the properties version of
x may appear to break the principle of encapsulation, but it doesn't. If, in the future, I wish to change the implementation of x, I could do something like this:Clients of the code will then be able to use the
x property in the same way they always did.This method of defining a clear contract for a property can also be extended to vector properties, in which the property contains a collection. It can be done fairly generally, so that the collection property may be backed in various ways by pre-existing collections (in the same way that you could implement a
Map as a HashMap or a TreeMap or whatever).A final advantage of these properties arises when they are bound into a GUI. For example, I have a text field derivative called
BoundIntField which displays an integer value. To create an instance of this class, bound to property x I do the following:And... that's it! The
BoundIntField automatically listens for changes to x and updates itself. Also, when BoundIntField loses focus or receives an enter key press, it updates x. This is all done without breaking encapsulation, and without me having to write any duplicate glue code at all!

No comments:
Post a Comment