|
|
||
Rémi Forax's BlogJanuary 2007 ArchivesProperty ReloadedPosted by forax on January 23, 2007 at 08:26 AM | Permalink | Comments (27)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
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").
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<? extends Bean, T> 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
Kitchen Sink Language and local keywordsPosted by forax on January 15, 2007 at 02:54 AM | Permalink | Comments (0)The Kitchen Sink Language (or ksl) is open here : ksl.dev.java.net, so i hope that the next version of my prototype will be the ksl trunk. Before trying to commit compiler patches that introduce local variable type inference or properties to the ksl trunk, i think i will write a small patch that enable the use of local keywords. Local keywords
What is a local keyword ? A local keyword is a
keyword that is only enabled at some locations
in the grammar and that is considered as an
identifier elsewhere.
Just a word about properties, i have read lot of blogs about that, i have even dreamed about that this week end (a kind a nightmare in wich a property told me that she needs to be bound). So i have decided to take some rest. Rémi Property and interceptorsPosted by forax on January 11, 2007 at 08:10 AM | Permalink | Comments (15)Since my last post, Cay Horstmann has recalled that properties are intended for tools and Hans Muller bid up by saying that property syntax is useless without a way to define bound properties. Interceptors and bound properties
What Hans want is some kind of interceptor.
An interceptor is an object or a method that can trap access
to a property. In Java, these objects are implemented
either using java.lang.reflect.Proxy or by
bytecode enhancement using a
VM
agent or a special classloader.
So for me, instead of trying to re-invent the wheel, we could perhaps transpose the concept of server side interceptors in Swing world. We 'just' need an equivalent to an EJB container for swing application. I think the concept of transaction can be borrow in the same time, it could liberate us from invokeLater and SwingWorker.
So in my opinion, adding bound properties
to the language is a bad idea.
So is property syntax usefull ? I think that even if bound properties are not managed by the compiler, we need a property syntax at least to insert a special attribute in the bytecode that will be recognize by the reflection runtime to provide property objects at runtime. Property interceptor by the compiler But if you think that this kind of AOP must be done by the compiler, i propose to allow to declare two a special methods named set* and get* (the star is not a typo) that can be used instead of a particular getter or setter. By example, a bean that declares two bound properties background and foreground in that way could be written like that :
public class MyBean {
public property Color background;
public property Color foreground;
public void set*(Property property,Object value) {
Object oldValue=property.get(this);
super();
SwingPropertySupport.firePropertyChange(property,
oldValue,property.get(this));
}
}
The compiler will generate foreground or background
setters by duplicate the set* code
for each setter.
To Link a property to a listener, we can use
MyBean bean=...
SwingPropertySupport.addPropertyChangeListener(
bean,"background",new PropertyChangeListener() {
...
});
Cheers,
P.S : to the little Peter, you can't return a gift :) Property and bean specPosted by forax on January 08, 2007 at 02:20 PM | Permalink | Comments (7)Among the questions about my property proposal and its implementation. One can be answered easily. Why don't provide property change support ? Because there are several ways to implement a property change support depending on what you want. I've try to categorize them, conbinations are possible:
I hope you are convinced. Cheers,Rémi All your property are belong to usPosted by forax on January 05, 2007 at 08:01 AM | Permalink | Comments (29)
Happy new year everyone.
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).
The current prototype has the following limitations:
The current 'spec' has the following limitations:
The patch againt Open JDK compiler 1.7b5: How to use the prototype ?
To enable the property syntax, call javac in this way:
cheers, Rémi | ||
|
|