It's pretty common to override the "toString" method in your classes so that they'll return something useful when used as a string. It doesn't always work though... A quick working example:
class Example1 {
private var data:Number;
public function Example1(data:Number) {
this.data = data
}
public function toString():String {
return "Example 1 [" + data + "]";
}
}
This is a pretty simple example just to illustrate a point. The above class would be used like this:
var t:Example1 = new Example1(17);
trace(t); // output: Example 1 [17]
Hopefully you can see that this technique can be pretty useful, especially for debugging purposes. However, there's an nteresting quirk that I've run in to that I wanted to share with everyone.
When you create a class that extends MovieClip, things don't work as expected. Consider the following:
class Example2 extends MovieClip {
public function Example2() {
// do something here
}
public function toString():String {
return "Example 2";
}
}
In theory we can associate this class with a MovieClip (via AS2 Class in the linkage properties in the library), give the MovieClip an instance name, and trace the instance name to see "Example 2" in the output window. Does this work? Nope, not at all. We just see the path of the MovieClip in the output. However, if you explicitly call the toString method, we see the expected output.
So why does tracing an instance name of a MovieClip not implicitly call the toString method? Whenever an Object is used as a string, toString should be called automatically. This isn't just a "Flash-thing," this is pretty standard programming practice.
At first I thought that maybe the original toString function couldn't be overwritten. That doesn't seem to be the case:
// instance of "test_mc" on the stage
// let's see what we have originally
trace(typeof(test_mc.toString)); // function
trace(test_mc); // _level0.test_mc
trace(test_mc.toString()); // [object Object]
// overwrite toString
test_mc.toString = function() {
return "test_mc.toString() called";
}
// did it work?
trace(test_mc); // _level0.test_mc
trace(test_mc.toString()); // test_mc.toString() called
From the results of the trace statements (the last line, specifically), it's clear that overwriting toString worked just fine for a MovieClip. Also, from Example2 above, when you trace(instanceName.toString()) you see that toString was overridden as well. So, if we can override toString.. why doesn't it work?
The conclusion this leads me to is that MovieClips are treated differently by the player virtual machine when they're used as strings. Instead of implicitly calling the "toString" method, the full path to the MovieClip is returned ignoring the "toString" method altogether..
Now.. the question of the night... why? Honestly, I'm not sure myself. I'm wondering if it has to do with eval at all. Anyone have any insight/ideas?