AS3 makes some strange things possible. Even stranger, it seems to do this without any warning by its compiler: MXMLC. It seems as though one of these strange things is the ability to override the variables of your parent classes.

Normally, a class is considered to hold all the member variables it declares as well as all of those member variables declared by its parent classes. So, the following should result in a conflict:

class Parent
{
	private var name:String;
}
class Child extends Parent
{
	// Already have a "name" in Parent
	private var name:String;
}

However, the compiler is just fine with this: no warnings and no errors. This can cause headaches and confusion. Consider the following:

class Parent
{
	private var name:String = "parent";
	public function Parent()
	{
		trace("parent sees name as: " + name);
	}
}
class Child extends Parent
{
	private var name:String = "child";
	public function Child()
	{
		trace("child sees name as: " + name);
	}
}
 
new Parent();
new Child();

Here, we have assigned different values to name. Which takes precedence? The results of this initial test shed a little light:

parent sees name as: parent
child sees name as: child

But perhaps this is caused simply because Parent initializes first, prints “parent”, then Child initializes and prints “child”. Let’s write a little more code to examine the state of these objects after they’re fully instantiated:

class Parent
{
	private var name:String = "parent";
	public function Parent()
	{
		trace("parent sees name as: " + name);
	}
	public function printName(): void
	{
		trace("printName: " + name);
	}
}
class Child extends Parent
{
	private var name:String = "child";
	public function Child()
	{
		trace("child sees name as: " + name);
	}
	public function childPrintName(): void
	{
		trace("childPrintName: " + name);
	}
}
trace("--instantiate parent--");
var p:Parent = new Parent();
 
trace("\n--instantiate child--");
var c:Child = new Child();
 
trace("\n--p.printName()--");
p.printName();
 
trace("\n--c.printName()--");
c.printName();
 
trace("\n--c.childPrintName()--");
c.childPrintName();

The first two tests should be obvious from the first test. They print:

--instantiate parent--
parent sees name as: parent
 
--instantiate child--
parent sees name as: parent
child sees name as: child

Then we call printName() on the Parent and Child instances and get:

--p.printName()--
printName: parent
 
--c.printName()--
printName: parent

This would seem to support the order-of-execution explanation of what’s going on. However, it’s not true. One final test blows this theory out of the water. We call childPrintName()

--c.childPrintName()--
childPrintName: child

The truth is revealed! We see here that behind the scenes there are really two name fields of a Child object. The private scoping on the variable seems to go one step further than in other languages and actually scope the private variable to only the class declaring it, not simply disallowing access to children. While weird, this actually makes a lot of sense once you know it and explains some issues you may be seeing. The downside is the ease of inadvertently overriding a variable and all the confusion that ensues afterward, at least for those that haven’t read this article. You have, so please explain it to them for me.