Some notes on overriding "toString"

| 4 Comments

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?

4 Comments

MovieClips are treated differently in a lot of respects. But I'd call it a bug myself...

in flashMX days,
the only way to override the movieclip toString method was to use the non-official way of inheriting

Cf:
someClass.prototype.__proto__ = MovieClip.prototype;

someClass.prototype.__constructor__ = MovieClip;

but even with that you need to force the toString:
trace( some_mc.toString() );

not because you can't override the toString method, but due to how trace() work internally,
I presume trace() first check the primitive type of the object and for a movieclip object it does not apply a toString but return the target internal property..but I have nothing to proove that

for that matter I never use the default trace() directly and use an equivalent wich force the toString call before trace()

I'm also finding that when you attach a custom classd to a clip, nested clips don't receive mouse events.

Leave a comment



About this Entry

This page contains a single entry by darron published on January 15, 2004 7:27 PM.

Getters and setters are evil was the previous entry in this blog.

What's your Geek Code? is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Archives

OpenID accepted here Learn more about OpenID
Powered by Movable Type 5.02