Since I wrote the last entry about properties, the comments and Groovy changed my mind about the property syntax:
- I think the accessor method syntax that panzi proposed is much better than my Java-like syntax or the C# syntax.
- If the language uses the 'virtual' keyword for virtual methods, virtual properties (properties without associated member field) can not use 'virtual' as a keyword. Otherwise it would not be possible to override the accessors in a sub-class. But the keyword is not needed anyway, because the new accessor syntax can unambigously define a property. You just need to write one or both accessor methods. For the API documentation only one accessor method must be documented, and it should be documented like a field (and not like a function)
- Groovy has the simple and effective idea that all public field members are
properties. This removes the need for the 'property' keyword and also the difference between properties and fields. Just add a regular member, and it is accessed using auto-generated accessor methods, that can be overwritten by you - There's one drawback when properties are accessed like field-members: you can't control anymore whether you access the field directly, or using the accessor methods. This can only be avoided with a syntax extension, and I think the least painful is the following: a method can access the raw field member of the object class without the accessor methods by prefixng the name with a '@'. It is not allowed to use this kind of access for other instances or classes (thus only '@field' is allowed, but never 'ref.@field').
In order to prevent errors, the accessors must not call themselves and
thus the attempt to read the field without '@' would cause a compilation error.
Here is the example class with these changes:
class SubString {
private int mEndIndex;
/// Documentation!
public int beginIndex;
/// Documentation!
public int length.get() const {
return mEndIndex - @beginIndex;
}
public void length.set(int value) {
mEndIndex = value + @beginIndex;
}
};
It's short. I am not very happy about the '@' thing though.

Re: Property Syntax Revised
hmmm, how about this:
class SomeClass { private: int mEndIndex; public: // flat means no value is stored internal. // maybe deep or storedvalue or something like that as opposide? flat property int length; property int beginIndex; SomeClass(void) : beginIndex.value(0) {} virtual ~SomeClass(void) {} property int length::set(int value) throw() { if( value < 0 ) throw out_of_range("SomeClass::length::set: value < 0"); // the attribute value is allways private // except the property is virtual, then it's protected (good idea? don't know) // or would it be better, when it where allways protected? mEndIndex = value + beginIndex.value; // the setter has to return a value, so the compile has not // to call the getter in expressions like i = (obj.prob = j); return value; } property int length::get(void) const { return mEndIndex - beginIndex.value; } property int beginIndex::set(int value) throw() { if( value < 0 ) throw out_of_range("SomeClass::beginIndex::set: value < 0"); // this->value would be confusing return beginIndex.value = value; } // hmm... or if no beginIndex::get() is declared then it will be accessed directly by default? // this would be a easy aproche but IMHO not clean. // this way you can define a readonly property be NOT declaring/defining ::set()! property int beginIndex::get(void) const { return beginIndex.value; } };rethought it again....
rethought it again....
class SubString { private: int mEndIndex; public: // the type after the keyword 'property' defines the // type of the value member of the property. // void means there will no value be stored property void length; property int beginIndex; SomeClass(void) : beginIndex.value( 0 ) {} virtual ~SomeClass(void) {} int length::set(int value) throw() { if( value < 0 ) throw out_of_range("SubString::length::set(int value): value < 0"); // the attribute value is allways private // except the property is virtual, then it's protected (good idea? don't know) // or would it be better, when it where allways protected? mEndIndex = value + beginIndex.value; // the setter has to return a value, so the compile has not // to call the getter in expressions like i = (obj.prob = j); return value; } int length::get( void ) const { return mEndIndex - beginIndex.value; } int beginIndex::set(int value) throw() { if( value < 0 ) throw out_of_range("SubString::beginIndex::set(int value): value < 0"); // this->value would be confusing return beginIndex.value = value; } // hmm... or if no beginIndex::get() is declared then it will be accessed directly by default? // this would be a easy aproche but IMHO not clean. // this way you can define a readonly property be NOT declaring/defining ::set()! property int beginIndex::get( void ) const { return beginIndex.value; } };better example, a std::string property:
class SomeClass { public: property string str; SomeClass( void ) : str.value( "initial value" ) {} virtual ~SomeClass( void ) {} // don't copy the string but allow only read acces through get() const string & str::get( void ) const { return str.value; } const string & str::set( const string & value ) { return str.value = value; } // so it's possible to do this in addition: string & str::get( void ) { return str.value; } // or this: const string & str::set( const my_string & str ) { return str.value = str.to_stdstr(); } };Borland did something like this, no?
I know with Pascal, they had properties that had virtual methods to set and get. If you did foo_property := 12;, it called the write for the property.
From deep in my memory, (actually cheated and googled)
published
property MyData: Integer read GetData write SetData;
end;
Didn't they do something with C++ with extensions to the specification?
__property int Width = {read=FWidth, write=SetWidth, default=200}
Derek
Re: Borland did something like this, no?
Didn’t they do something with C++ with extensions to the specification?
__property int Width = {read=FWidth, write=SetWidth, default=200}
Before I wrote the article I googled for property syntaxes in various languages, and some site mentioned a property attribute for C++. I don't know whether it was Borland though. The syntax is not impressing though. My focus is to make it short, readable and easy to remember; I don't think that this syntax achieves these goals.
Re: Re: Borland did something like this, no?
Borland and MS have both their own propritary property extensions.
)
The mentioned syntax is Borland's.
(It's all well documented in O'Reilis C++ in a Nutshell
Hmmm... a few thoughts.
Basically, you are doing away with the idea of fields altogether and replacing them with properties. I think this is a good thing, but in this case:
How does this strike you:
class SubString { private int mEndIndex; /// Documentation! public int length; /// Documentation! public int beginIndex; public length get { return mEndIndex - @beginIndex; } public length set { mEndIndex = value + @beginIndex; } }The raw values indicated with the '@' symbol would be referred to as property literals.
Strengths:
Weaknesses:
I think I like this more than C#'s style. C# style properties blur the lines between fields and member functions. I think this style completely melds the idea of fields and properties, but is still distinctive from the concept of member functions.
Re: Hmmm... a few thoughts.
Modeling the get/set blocks to look so much like methods causes excessive verbiage.
It's certainly shorter with the value keyword, but it causes a special case in the grammar. You could, with the same argumentation, also simplify the syntax for operator overloading.
Re: Hmmm...
Basically, you are doing away with the idea of fields altogether… and replacing them with properties.
Yes. Think operator overloading for fields.
If this is the case, I think one should be allowed to specify the get and set for a private field too. Aesthetics.
The syntax allows it, and actually it doesnt matter, because (unlike Java) the accessor methods can not be used as methods. So there's no reason to forbid it.
Another aesthetic problem I have with this is the lack of a raw declaration for the length property. I know, the accessors aren’t going to be using its value so it isn’t really needed, but I think it should be included for consistency.
I also hesitated because of this one. The argument that I convinced myself with is that the property declaration is redundant. And the programmer should not be forced to do redundant declarations.
The major qualm I have is the potential confusion WRT the raw value VS the get/set accessors. Their is no confusion with C# style properties as the private fields that hold the value are not directly tied to the property.
I see the problem... what about this: you can either declare a property with the field syntax, OR write accessor methods, but never both. In other words, no ambiguity, no '@'. If you write accessor methods you need to add a private field if you need storage.
I think this style further erodes the idea of a field and makes them even *more* like methods.
It makes them more flexible: you can change them later without breaking anything. This includes changing the design of a super class with protected fields without breaking the compatibility for subclasses.
Rethinking this through...
I modified my original comment after I had thought about it a little more. I definately feel the length declaration should be necessary as it reduces the verbiage required && makes the syntax more consistent/simple. Let me know what you think of the other points... ie, making the method VS property accessor syntax distinctive and making 'value' a keyword. I know you don't like to see 'value' so perhaps we can come up with another option...
Re: Rethinking this through...