Skip to main content

All your property are belong to us

Posted by forax on January 5, 2007 at 8:01 AM PST

Happy new year everyone.


Since my last post, i've done some homeworks :),

and i'm please to present you a new version of the
prototype java compiler which includes property support.

First, why properties ?, we have already fields and any IDE
have a menu item that can generate getters and setters, so why do,
we need properties ?

Why do we write getter and setter ?
The reason, is that when you use
a property, you don't want to know if its implementation use
a field or something else.
By example, you can first choose to implement it as a field
and later when a new feature is require change your code to use a method.
To be binary backward compatible,
a carefull developer will always define a getter and a setter,
even if the property is a field package visible,
but its a boiler plate code and i don't see a reason
why we should do that if the compiler ensure that
a change in the way property is written
will always be backward compatible.

The compiler must handle properties for you and
garantee that implementation change must be binary compatible
without writing boilerplate codes.

Defining a simple property

  public class PropertyPoint {
    property int x;
    property int y;
  }
  ...
  public static void main(String[] args) {
    PropertyPoint p = new PropertyPoint(1, 2);
    System.out.println(p.x + " " + p.y);  // replaced by p.getX(), p.getY()
  }

A word about the keyword 'property', 'property' is not a real keyword
like 'public' or 'enum', so you can have a variable named property
in another place in your code, i will still compile, even if you
create a class property, it will still compile.
Basically, if the compiler found the keyword 'property' in another place,
it consider it as an identifier or a type depending on its location.
This example, written by peter ahé, compiles :

  public class property { // see the name of the class ??
    public property int value; // a property
 
    // these stuffs are not properties
    property property;    // a field
    property() {          // a constructor
    }
    property property() { // a method
      return null;
    }
    property property(property property) { // another method
      return null;
    }
}

The compiler generates automatically a getter and a setter
and doesn't allow developers to define their own.
A property is accessed as a field (with dot) in the source code
and by a getter/setter pair in the generated bytecode.

Abstract property

An abstract property is a property that is not a field
thus can't be initialized by an expression.
It requires the developer to write a getter and a setter.
By example, i can tranform the class PropertyPoint to use
polar coordinates instead of rectangular ones.

  import static java.lang.Math.*;
  public class PropertyPoint {
    abstract property double x;
    abstract property double y;
   
    property double rho;
    property double theta;
   
    public double getX() {
      return rho*cos(theta);
    }
    public void setX(double x) {
      double rho = hypot(x, y);
      theta = atan2(y, x);
      this.rho = rho;
    }
   
    public double getY() {
      return rho*sin(theta);
    }
    public void setY(double y) {
      double rho = hypot(x, y);
      theta = atan2(y, x);
      this.rho = rho;
    }
   
    public PropertyPoint(double x, double y) {
      this.x = x;
      this.y = y;
    }
}
...
    public static void main(String[] args) {
      PropertyPoint p = new PropertyPoint(1, 2);
      System.out.println(p.x + " " + p.y); 
    }

You can notice that the source of the method main doesn't change
et even better, the generated bytecode doesn't change too.
Another example, that mix abstract property and field :

  class Button {
    private String label;
    public abstract property String text;
    public String getText() {
      return label;
    }
    public void setText(String label {
      this.label = label;
      repaint();
    }
  }
  ...
  public static void main(String[] args) {
    ...
    Button button = new Button();
    button.text = "toto"; // replaced by button.setText("toto");
  }

Property and type

It is possible to define a property in a
class or an abstract class, an interface (automatically public abstract)
or an enum, but not in an annotation
(currently not enforced by the prototype).


Allowed keywords for property are :

private protected public
final static volatile transient.


Allowed keywords for abstract property are :

abstract
private protected public
synchronized final static

The current prototype has the following limitations:

  1. properties are not recognized in an already compiled code.
  2. final property support is untested.
  3. abstract property doesn't check if a getter/setter exist
    in the hierarchy but only in the current class.

  4. property doesn't support ':=' initialization



The current 'spec' has the following limitations:

  1. using a property in the constructor leads to an unsafe
    publication of this.

  2. rules about overriding property are not defined nor
    the reflection API

The patch againt Open JDK compiler 1.7b5:

patch-1.7b05.txt


The prototype compiler:

prototype-1.7-b05.jar

How to use the prototype ?

To enable the property syntax, call javac in this way:


java -jar prototype-1.7-b05.jar -XDallowProperty Test.java

cheers,
Rémi

Related Topics >>