I’ve decided that in addition to posting code samples, applications, and packages for download I would also engage in trying to promote practices that I find helpful in making writing AS3 easier in the long run. What do I mean when I say these tips will make things easier? I mean that as you continue to work with code you’ve written, especially within larger projects, you should find it less difficult to track down bugs, interpret code you may not have looked at for some time, and share code with other developers.
The first tip has to do with namespaces and scope. If you’re at all familiar with object oriented programming and writing classes in AS3, you know that within a class you can declare variables to hold important data that are unique to each instance of the class. The built in namespaces available for these variables are public, private, and internal.
Today I’ll be discussing the public and private namespaces, and how you should use them when considering how an instance of your class will be used throughout your application.
For the purposes of making myself clear, suppose we’re tasked with creating a class intended to represent a person:
package {
public class Person {
public function Person() {}
}
}
A “Person” may have a number of characteristics we’d like to keep track of. For example, we may want each “Person” to be aware of his name, age, and gender. We can declare these values as members of each instance of the class by placing variable declarations within the brackets corresponding to the class definition. The question I intend to answer today is whether we should declare these values as public or private.
If you intend to pass instances of your Person class around your application, and you intend to retrieve the values stored within, it may seem that the simplest thing to do is to declare your class variables as public.
package {
public class Person {
public var name:String;
public var age:int;
public var gender:String;
public function Person() {}
}
}
This may seem like a good idea, as in the future you may want to access a person’s name like so:
var guy:Person = new Person();
guy.name = "franz";
trace(guy.name) // output: franz
However, suppose you have a large number of people you need to represent. Furthermore, suppose these people have their values extracted and used in a large number of places throughout your code. Furthermore, suppose after you’ve done the leg work of getting most of your application ready, it occurs to you, for whatever reason, that a person’s name should be in all capital letters. Now, you could track down every declaration of a person and replace the name with capitalized text…
var guy:Person = new Person();
guy.name = "FRANZ"
trace(guy.name); // output FRANZ
…or you could find every instance in which you want to output a name and do the following…
trace(guy.name.toUpperCase()) // output: FRANZ
…or you could have saved yourself a lot of time and trouble by doing things right in the first place. Let’s amend our existing class definition by making our member variables private, and by adding getter and setter functions for each of those variables:
package {
public class Person {
private var _name:String;
private var _age:int;
private var _gender:String;
public function Person() {}
public function get name():String {
return _name;
}
public function set name(val:String):void {
_name = val;
}
public function get age():int {
return _int;
}
public function set age(val:int):void {
_age = val;
}
public function get gender():String {
return _gender;
}
public function set gender(val:String):void {
_gender = val;
}
}
}
Now, if you want to make sure that every name is displayed in all caps, you can modify the name getter function like so:
public function get name():String {
return _name.toUpperCase();
}
…and voila! The next time you try to access a person’s name (any person, anywhere), you’ll get the desired output. Let’s enumerate the benefits of using this approach:
- You get application-level control over the values associated with your classes, without having to dig around for individual members.
- Because of the above, you’re less likely to miss members of your classes floating around in obscure functions, and so in the long run you’ll have fewer unpredictable bugs.
- You could theoretically call other functions every time a value is accessed for more complex interactions with your class.
- Using setters, you can filter values placed in your classes at an application-wide level.
One important point to remember is that the name of your getter and setter functions cannot be same as the name of the private variable you’re using them to access. I recommend prefixing the names of all of your private variables with some sigil (I’m fond of underscores) to deal with this, and later, when you’re making adjustments to your massive class, it’s easy to see at a glance while scanning through your code which variables are private and which are not.
That’s all for now. More tips will be coming down the pipelines in the future.