ActionScript Implicit Getters And Setters Are Growing On Me
Posted by
Brad Wood
Nov 06, 2008 19:09:00 UTC
Here's a little tidbit that will be old-hat to any Flex/Flash people out there, but as a CF guy, I found it pretty interesting. Most ColdFusion programmers have probably heard of implicit getters and setters as a pattern some have adopted in CFML (and others seem to vehemently oppose). While learning Flex, I have found that ActionScript 3 also supports implicit getting and setting but it means something completely different that what I had expected.In ColdFusion, the point of implicit getters and setters (As they are colloquially referred to) generally seems to be an attempt to leverage the dynamic flexibility of the language to reduce boiler plate code and find the most streamlined way (code-wise) to still retain the encapsulation of get and set methods to access private properties of an object. There are two main ways implicit gets and sets manifest themselves in ColdFusion.
OnMissingMethod()
In this approach, the OnMissingMethod method is employed to handle method names like getPropertyName() where "PropertyName" equals or maps to an internal property. I have an example of such a method in my experiments with Synthesized Objects that is used something like this:[code]<cfscript> myObject = createobject(...) myObject.setProperty1(value); foo = myObject.getProperty1(); </cfscript>[/code]
Generic get() and set()
This approach is similar in the previous in that is uses a single generic method to handle multiple properties. It requires a generic get method and a generic set method which allow for the name of the property in question to be passed in along with a value in the set case. They usually look something like this:[code]<cffunction name="get"> <cfargument name="property"> <cfreturn variables[arguments.property]> </cffunction> <cffunction name="set"> <cfargument name="property"> <cfargument name="value"> <cfset variables[arguments.property] = value> </cffunction>[/code]And usage looks like this:
[code]<cfscript> myObject = createobject(...) myObject.set("property1",value); foo = myObject.get("property1"); </cfscript>[/code]Note, both of these methods often use either a list of acceptable properties or cfproperty Meta data to control what can be set and retrieved. Both of these methods also are an attempt to not be required to write each get and set individually, but still use them.
How ActionScript Does It
Implicit getters and setters in ActionScript are sort of the opposite. They require you to still write our all your get and set methods, but you get to use them without looking like you are calling a method. In other words, your code has the natural appearance of directly accessing properties even though getters and setters are actually being called in the background. Usually people name the getters and setters the same as their property name (or at least the way they want it to be externally accessed). The get and set methods are allowed to share the same name, but the property itself has to be called something different. Usually an underscore is appending to the beginning of the private variable name. This is what it looks like:[code]TestClass { var private _property1:String; public function get property1():String { return _property1; } public function set property1(value:String):Void { _property1 = value; } }[/code]Note the extra "get" and "set" keywords before the method name. This is how they are used:
[code]myObject = new TestClass(); myObject.property1 = 'foo'; var bar:String = myObject.property1;[/code]It would appear we are directly accessing the property, but in reality it is being handled by the getter and setter method. The programmer isn't saving on any lines of code per se, but I do like the way it can un-clutter the code when doing a lot of gets and sets. Especially when nesting gets such as:
[code]object.internalobject.yetagain.property1[/code]as opposed to
[code]object.getinternalobject().getyetagain().getproperty1()[/code]On a side note, Railo is reported to already allow for this functionality if I understand correctly under the name Magic Functions but I have yet to try it out. Perhaps ColdFusion 9 will allow for something like this.
Joe Rinehart
Hey Brad,
Ack, I've been misquoted. I oppose generic getters and setters, but I'm all for implicit support in CF. They're not at all the same.
http://www.firemoss.com/post.cfm/CF9-Feature-Wish--Properties-please http://www.firemoss.com/post.cfm/Getters-and-Setters--a-different-CFC-approach
Brad Wood
Sorry about that Joe. I was hoping I wouldn't link to the wrong argument at the wrong place. I'll go ahead and remove the link to the "debate" at your blog so you aren't misrepresented. :)
Tell me though-- when you say you are a fan of implicit support, do you mean the way ActionScript does it, or the onMissingMethod method. People use the term implicit to mean both, but if I had to guess I would say you probably probably group the onMissingMethod way in the "generic" camp since both of them lose the API for the object.
If we were to roll the generic get and set as well as the onMissingMethod stuff in a single group, that is what you SEEMED to be opposed to, and that is is what I was trying to convey in the opening paragraph.
Derli
I am confused now if as you said "...but the property itself has to be called something different"
How can the compiler know which method goes with a property ?
Brad Wood
@Derli: The compiler doesn't know what property goes with the setter/getter. The good news, it doesn't need to know. In fact, a getter and setter might not map to a single property.
For instance, in ActionScript you could have a getter method called fullName which returned the first and last name combined toghether. The reason implicit getters and setters in AS are cool is becuase you don't have to access that method like myPerson.FullName(). You can just do myPerson.fullName. Notice it looks as though you were directly accessing a fullName property, but in reality, the compiler is just accessing the fullName getter method in the background. Also note, you aren't allowed to have an actual property called "fullName" because the compiler wouldn't know if you were accessing the property directly, or calling the method.
Does that make better sense?
Tim Oxley
So in essence, it's allowing the get function to be called without () and the set function to be called when the function is used as the LHS of an assignment... with the RHS becoming value I wonder if this could be used to simplify other operations somehow...