Skip to main content

Property Reloaded

Posted by forax on January 23, 2007 at 8:26 AM PST

This entry is the second draft of my property proposal, i have tried to gather all the ideas proposed since my first post about properties.

Why do we need a property syntax in Java ?

If you have not followed the different blogs, i recommend you to first read properties in Java by Richard Blair and Properties are design features by Cay Horstmann.

Declare a property

There is three kind of property, simple property that are translated to a field plus a getter and a setter automatically generated by the compiler, user-defined property, a property for which getter and setter are defined by the developer and abstract property, a property for which getter and setter are abstract. All kind of properties can be read-only, write-only or read-write.

  class MyBean {
    public property String name1; // read-write
    public property String name2 get; // read-only
    public property String name3 set; // write-only
    public property String name4 get set; // illegal

    public property String name5 get { return "hello"; } // read-only
    public property String name6 set(String name) { } // write-only
    private String _name7;
    public property String name7
      get { return _name7; }
      set(String name) { _name7 = name; firePropertyChange(name7); } // read-write
  }

As i have already said, property, get and set are not real keywords but only local keywords. A property is implicitly read-write so the syntax for name4 is illegal. All other combinations that the ones above are invalid. You can also notice that if the property is not abstract and ends with a semi-colon, a field is created.

Access to a property

Unlike my first proposal, i think now that we must not have two ways to access to a property. So 'dot' can't be used to access/change the value of a property (It has another meaning, see further). In order to permit retrofitting of already existing code, properties are accessed using getXXX/setXXX. It's a little awkward especially for beginners but i really think that is the best solution.

 MyBean bean = new MyBean();
bean.setName1(bean.getName2());

Property Litteral

Because i'm lazy, instead of defending myself property literal, i prefer to redirect you to Evan Summers's property reference or Stephen Colebourne's property objects
Matthias Ernst proposed to create a property object by property and by object. I think it is not very feasible due to the memory comsumption. I think a system ala java.lang.reflection, i.e. one property object by property and not related to an instance is more realisic.

I propose to use dot on the class to access to such object.

  Bean bean = new Bean("joe", "forax"); 
  Property<Bean, String> name = Bean.name;
  name.set(bean, "rémi");
  Property<Bean, String> lastname = Bean.lastname;
  String myname= lastname.get(bean);

A property literal is like .class, it acts like a static final field. The compiler translates ClassName.propertyName to ClassName.class.getProperty("propertyName").
Perhaps the property object can be cached to avoid one lookup by call like .class in transalted by the compiler in pre-tiger release.

Property Litteral and generics

The idea is to make Property safe, so a property is typed using generics. I propose to parametrize a property objet Property by its bean type and the type of its value.

 Property<Bean, String> prop = Bean.name;

Bound Property

A simple property can be bound to make swing hackers happy. If such property is defined in the class, a method propertyChange() is required in the class or in on of its supertypes. A bound property is always read-write.

 class Point {
    public property int x bound;
    public property int y bound;

    private <T> void propertyChange(Property<Point, T> prop, T oldValue, T newValue) {
      // do what you want here
    }
}

The compiler translates the bound property x into :

 private int x;
public int getX() {
   return x;
}
public void setX(int x) {
   int oldX=this.x;
   if (x!=oldX) {
     this.x=x;
     propertyChange(Point.x, oldX, x);
   }
}

Property Litteral and switch

Property litteral like enums can be used in a switch. This features is easy to implement if bug 5029289 (switch on strings) is implemented.

 Bean bean=new Bean();
bean.addPropertyListener(new PropertyListener<Bean>() {
   public <T> propertyChanged(Property<Bean, T> property, T oldValue, T newValue) {
     switch(property) {
       case name:
         frame.setTitle((String)newValue);
         break;
       case value:
         slider.setValue((Integer)newValue);
         break;
     }
   }
}

Like enums, case items are not qualified. The compiler verifies that as the variable property is typed Property the properties Bean.name and Bean.value exist.

The class Property

Just a preview of the methods of the class Property.

  public class Property<B, T> {
    public Class<B> getDeclaringClass() {}
    public Class<T> getType() {}
    public String getName() {}
    public boolean isReadable() {}
    public boolean isWritable() {}
    public T get(Object bean) {}
    public void set(Object bean, Object value) {}
  }

  public class Class<T> {
    public Property<T, ?>[] getProperties() {}
    public Property<T, ?> getProperty(String name) {}
  }

The signature of getProperties() is illegal with the current JLS but i hope it will be legal with the next JLS.

I will implement this spec functions of your comment, cheers
Rémi

Related Topics >>