 |
All your property are belong to us
Posted by forax on January 05, 2007 at 08:01 AM | Comments (29)
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:
- properties are not recognized in an already compiled code.
- final property support is untested.
- abstract property doesn't check if a getter/setter exist
in the hierarchy but only in the current class.
- property doesn't support ':=' initialization
The current 'spec' has the following limitations:
- using a property in the constructor leads to an unsafe
publication of this.
- 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
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Neat.
> using a property in the constructor leads to an unsafe publication of this.
How is that?
Posted by: mernst on January 05, 2007 at 08:43 AM
-
Hi matthias, an access to a property is replaced by an accessor, so
a potentially overridable method can be called in a constructor.
not a very good idea.
Rémi
Posted by: forax on January 05, 2007 at 08:56 AM
-
Ok - that's unavoidable. I was confused - "unsafe publication" immediately reminded me of concurrency and memory model ...
Posted by: mernst on January 05, 2007 at 09:05 AM
-
It looks cool, but have very little practical use without support in the major Java IDE's...
Posted by: euxx on January 05, 2007 at 09:09 AM
-
I'm very glad that you've done away with the arrow operator; the syntax here is almost exactly what I was hoping for, and may be better.
The only concern is that it won't provide a convenient way to access existing properties; the beans convention, while deplorable in some ways, is widespread. It'd be handy to be able to do frame.visible=true without having to change JFrame's code.
As far as I can tell, there's no 'property inference' here. What's the rationale? I hope it's just 'time'. ;)
Posted by: ricky_clarkson on January 05, 2007 at 09:31 AM
-
Kool, Very Kool :)
I will try it later ~
In the following code:
public class PropertyPoint {
property int x;
abstract property int y;
public int getX() {
return x;
}
}
p := new PropertyPoint; // :)
Beside, using the p.x to access to the can we still call write p.getX();
If it is okay, we will have to ways to call the property. Is it good ?
Posted by: fcmmok on January 05, 2007 at 09:38 AM
-
Lots of people talk about how the language should evolve (including me), but here you are again giving people something to play with. Thats very refreshing. I going to have to try it. What are your thought on overriding property accessors?
Posted by: aberrant on January 05, 2007 at 11:52 AM
-
Noooooooo! Wrong syntax.
When I read a.b=c in code, how do I distinguish a public variables assignment from property set (which is really a method call)? Readability is one of the key values in Java. This is a step in the wrong direction.
As ugly as the arrow is, that's the key virtue. Different than dot syntax = no ambiguity.
Posted by: jmaline on January 05, 2007 at 01:43 PM
-
@ricky_clarkson, good question, i prefer hoping that
swing code will be retrofited to use property instead of trying
to infer it
@jmaline, the idea is to remove public fields which is not a good idea (tm)
and replace them by properties.
Posted by: forax on January 05, 2007 at 02:05 PM
-
@forax
I have a very serious question !
, Can we can call the getX() and getY() in ur syntax proposed above !!!
Posted by: fcmmok on January 05, 2007 at 03:14 PM
-
@forax, Take public (protected? package?) instvar access out of the language and I'll buy your point. Short of that, I stand by my point. Recommended good style for code I write is different than the body of code I'll read. And my concern is about readability.
I regretfully say, bring on the ugly arrow if you want this. Or something else. But you get the dot only when you pry it from my cold, dead hands. :-) Don't turn Java into an unreadable mess.
Posted by: jmaline on January 05, 2007 at 03:36 PM
-
Properties should be seen as accessible fields that can be declared in an interface. With this definiton p=x and x=p (which is the property?) is completly sound and unambigous. They are not a shothand for get/set pairs (they are as well).
I have a problem with the getP/SetP. This gives me now two ways accessing the property. This will lead to enless debates about readability amoung code style guide writers (aka the people who can neither read nor write code)...
The get/set should be defined "inside" the property to dispatch these events without altering any values:
private double _a;
abstract property double a;
double getA(){return 5*_a;}
void setA(double a_){ _a= a_/4};
a=2;
assert (a+a==5); // rats!
Your polar/cartesian example is tempting, but I still feel that abstract properties are harmful. Actually I am missing non-abstract properties in interfaces. Note that the usual problems of multiple inheritance don't apply here as the semantics of any property "p" is identical - it behaves like a pair of accessors which don't alter anything.
Posted by: csar on January 05, 2007 at 10:30 PM
-
If you guys are interested in discussing the new Property support you might want to head over to javalobby where there's a thread about this.
Cheers,
Mikael Grev
Posted by: mikaelgrev on January 06, 2007 at 04:01 AM
-
@fcmmok, currently you can't directly access to getter and setter
but because i've made a mistake.Perhaps an intermediary solution is
to allow acess throught accessor with -source 1.6
and to emit a warning if you compile with -source 1.7.
@jmaline, i've another solution to this problem.
i've planed to emit a warning in case of public and protected fields
to explain to newbies that they can use a property instead :)
@csar, i don't catch your p=x and x=p, could you provide an extended
example ?
By inside, you mean like in C#, between '{' and '}', i don't like this syntax
not because the curly braces but because it doesn't allow you to
declare a covariant return type for the getter.
I agree that this example is stupid
abstract property Object object;
String getObject() {
return object; // object should not be available
}
...
and perhaps it could be a great idea to remove the property
from the scope of its accessors. I want to minize the changes to
convert a getter/setter to a property.
Posted by: forax on January 06, 2007 at 07:25 AM
-
About properties working with existing code, Rémi said:
"good question, i prefer hoping that swing code will be retrofited to use property instead of trying to infer it"
That sounds unlikely, and doesn't provide any solution for working with existing bytecode rather than source (such as bytecode that has to be compatible with more than one Java version, or for which the source is unavailable).
The get/set convention is so widely known that I don't think there is any problem with inference based on it.
Posted by: ricky_clarkson on January 07, 2007 at 05:37 PM
-
Remi,
Please explain me this anti-C# anti-Delphi hype.
Why Java needs property in it's own way??? Why not to use very clear syntax that requires a lot of typing???
How that
// field decl ommitted
abstract property public String name;
public String getName(){...}
public void setName(String value) {...}
Is better then
// field decl ommitted
public /*virtual | override*/ property String name {
get {...}
set {...}
}
Is there anyone who re-defines return type for getter, parameter type for setter?
What else is advantage of your syntax besides verbosity?
Your proposal even worse then existing properties in AS3 (and they have historical reasons to exists):
// field decl ommitted
public function get name():String {...}
public function set name(value:String):void {...}
Valery
Posted by: vsilaev on January 08, 2007 at 08:05 AM
-
It's not a hype. C# implements what i have called abstract property,
the compiler requires to write getter and setter. I think it is not always
necessary. So simple property generates getter and setter,
that are required to ensure binary compatibility.
> Is there anyone who re-defines return type for getter, parameter type for setter?
yes, at-least me. But that is not so important.
In Java, we write getter and setter, so why not continueing to use it
in case of abstract property, it reduce the cost of retrofiting your code
to use properties.
> what else is advantage of your syntax besides verbosity?
Avantages against C# or against hand written getter and setter.
Againt C#, no more than reducing the verbosity and some
subtilities with using a property in consctructor, i will talk later.
> Your proposal even worse then existing properties in AS3
why ?
Rémi
Posted by: forax on January 08, 2007 at 08:28 AM
-
What I would really like to see is in addition to the generation of getters and setters, also an automatic implementation of firing of property change events.
Posted by: vhi on January 08, 2007 at 09:13 AM
-
Personally I don't like this property syntax much. The difference between (private) field and (public) accessor/mutator is so significant that it deserves different syntax, I believe. What I would like to have are simple @Get, @Set and @GetAndSet annotations from which compiler would generate appropriate methods. Of course I would be able to write them myself, conflict should lead to compile-time error.Users of these getters and/or setters wouldn't even know that they aren't hand-written, but compiler-generated.As a nice bonus, standard Java API would provide utilities simillar to Jakarta Commons Beans :-)First usage scenario I can come up with is setter-based dependency injection. I really don't like the mess of IDE-generated setters.
Posted by: ladicek on January 08, 2007 at 09:16 AM
-
Remi, looks awesome.
@Ricky, I'm on the fence. I see where you are coming from, but at the same time you can scan the javadoc (or the popup in your IDE of choice) and see what is a property, and what is just a get/set method. I'd like to see frame.visible = true work too, without having to change JFrame, but I don't know how practical that is for the compiler. Hmmm.
Posted by: rbair on January 08, 2007 at 11:08 AM
-
Ricky and Richard, the problem with inference is than if you do that
you can't use dot to access to a property.
In the example below the infered property has the same name
that a field.
public class A {
int a;
public void int getA() {
return 0;
}
public void setA(int a) {
}
}
This clash doesn't exist if we explicitly declare property.
Rémi
Posted by: forax on January 08, 2007 at 02:32 PM
-
[blockquote]
the problem with inference is than if you do that you can't use dot to access to a property
[/blockquote]
I see. Hmmm. Let's say that I use Ruby (via JRuby) to create a Class. I compile it to bytecode. Is there anyway I can use the "." notation to access properties on that Class? (Does Ruby support Properties in the language??). Or more generally, how does the compiler know that there is a property? How would that be exposed for other languages that compile to bytecode?
Posted by: rbair on January 08, 2007 at 03:42 PM
-
And yet another "feature" is added to Java "because C# has it" (or insert your favourite language that has a way to circumvent private member access like this).
They should rename Java to RubPyC#++-- or something like that, it makes it far more clear what Java is becoming these days, an ugly mixed bag of the failed features of every other language out there.
Posted by: jwenting on January 08, 2007 at 10:49 PM
-
Richard, i've not talk about how properties are coded
into the bytecode. Basically, the compiler flags generated property
fields and property getter/setter (generated or not) with a special
bytecode attribute named Property.
So any languages targetted to the Java VM could declare its own
properties if it follow that scheme and these properties will be
recognized as Java property by javac.
jwenting, could you explain why property is a failed feature ?
Posted by: forax on January 09, 2007 at 12:29 AM
-
Remi,
I need non-trivial setter for more then 50% of properties. Specifically, in UI components, where I have to adjust other parts of inner state on property change. So I need to use your abstract property notation more frequently then trivial declaration. And I'm not satisfied with proposed syntax because it has:
Verbose syntax that is hard to write: Even with AS3 it's shorter then your proposal. You force me to type type 3 times. Even with existing pseudo properties I do it only 2 times. Also I have to type name(s) of property 3 times
Verbose syntax that is hard to read: even you place declaration of abstract property at one place and implementation in another place, what to expect from other developers... Looking at declaration no one can safely guess whether property is R/W or R/O and what access type it has.
The real problem with existing C# properties is that visibility modifier is shared both for getter setter. Plus this explicit getters/setters...
Btw, I don't now how your compiler handles visibility overrides... Same as C#?
abstract property String name; // package-visible
public String getName() {} // public
protected void setName(String value){} // protected
Actually, C# 3.0 will support automatic properties. Why not to try this direction without current C# limitations? Say, something like following:
public property String name; --- R/W property with automatic getter/setter. Visibility of getter/setter inherited from property definition
public property String name {get; set;} -- same as above, but we may put (method-level?) annotations on get/set
property String name {public get; protected set} -- R/W with automatic public getter, protected setter.
public property String name {public get; private set;} -- compiler error, incorrect visibility redefinition
public property String name {public get; public set;} -- compiler error, incorrect visibility redefinition; i.e. it's allowed to use visibility modifier at one place only
property String name {
public get {...}
protected set { /*value used as parameter here */ ...}
} -- fully customized property
I know, package-visibility is not addressed here. But do you see any shortcomings besides this? Thoughts?
Valery
Posted by: vsilaev on January 09, 2007 at 01:20 AM
-
Valery,
Verbose syntax
yes but backward compatible. I prefer having one way to
declare getter and setter. We already have it, so even if you have to
type more characters, it is more readable because it's a pattern.
R/W or R/O property
a read-only property is flagged final.
I am not entirely happy about that but i haven't
found something better.
I've read the C# 3.0 spec in details and frankly that part is a mess,
it's overspecified and i hope nobody will use that.
From my own experience, we want different modifiers only in
rare cases and we can use an abstract property for that.
Cheers,
Rémi
Posted by: forax on January 09, 2007 at 02:45 AM
-
Remi,
If backward computability is a major concern, then JUST DON'T ADD THIS FEATURE! I'm sick of type erasure already! I'd better use new language for JVM like (J)Ruby or Groovy.
Back to topic
There are at least 3 different groups of users who may benefit from new property syntax: developers of libraries, developers of applications and tools vendors.
My opinion is that your proposal has value for developers of applications, adds nothing for tool vendors (besides great opportunity to re-write their tools ;) and makes life of library developers more complex due to too verbose syntax. In short, the changes necessary to language according to your proposal far outweighs benefits.
I'd like to see more complex example from you that describes new property syntax in relation with:
Reflection API
Annotations
JavaDocs
Valery
Posted by: vsilaev on January 09, 2007 at 03:48 AM
-
@valery, from a framework developer standpoint, the existing JavaBean API would have be updated to include property syntax, allowing the PropertyDescriptor[] returned to include the newly declared properties along side the legacy declarations. 95% of all bean code that I've seen used in libraries are backed by the Bean Introspector and PropertyDescriptor API, so making accomodations there would make everything 'just work' in most cases.
Posted by: jhook on January 09, 2007 at 12:47 PM
-
I regretfully say, bring on the ugly arrow if you want this. Or something else. But you get the dot only when you pry it from my cold, dead hands. :-) Don't turn Java into an unreadable mess.
I totally agree. I wouldn't mind to have properties in SE7 and I wouldn't mind not having them, but if they make it in, then please please please use the "." notation or anything that is more aesthetic than "->" because the arrow notation is *REALLY* ugly and hard to type.
Posted by: wtff on January 20, 2007 at 09:30 AM
|