Home > Dev > Customizing toString()

Customizing toString()

September 8th, 2008 Leave a comment Go to comments

When writing classes for a framework I usually put a custom toString method into important classes so that debugging becomes easier. Normally they would go like something along the lines of:

override public function toString():String {
	return "[ClassName]";
}

… Sometimes adding properties to the returned String that give back information about the class, e.g.

override public function toString():String {
	return "[ImageClass, size=" + _size + "]";
}

But writing them rigid like that is a disadvantage when you decide later to refactor class names. Admittedly it’s also not a very elegant way so I got the idea to take the class name that is returned by getQualifiedClassName(). The only problem is that getQualifiedClassName not only provides the type name but also the whole package String of the class. Regular Expressions to the rescue! After twiddling around with them for a while (I’m by no means a RegExp expert) I got my toString method into the shape that I desired:

override public function toString():String {
	return "[" + getQualifiedClassName(this).match("[^:]*$")[0] + ", size=" + _size + "]";
}

This way it matches the String returned by getQualifiedClassName with the Regular Expression [^:]*$ which checks from the right end for an arbitrary text up to the first occurring colon, but without including the colon. Taking the first element of the Array returned by match() and you got what you need!

A nice way of using this is when writing abstract classes that contain the toString method and any subclass can use that toString method without the need to override it … that is of course unless you want ot add other output information.

  1. September 8th, 2008 at 17:09 | #1

    That’s some smart code right there. I’m going to include it in the next release of the Gaia framework and really all my work from now on. Thanks for the great tip!

  2. September 8th, 2008 at 18:32 | #2

    Thanks Steven! I improved the toString method a little more today … I’m using a base Class named BasicClass from that other classes can extend if they need toString. The BasicClass then gets the following:

    public function toString(...args):String {
    	var s:String = "";
    	for each (var i:String in args) s += ", " + i;
    	return "[" + getQualifiedClassName(this).match("[^:]*$")[0]
    	+ s + "]";
    }

    That way you could add any number of additional debug information comma-separated as an argument.
    Sub-Classes then just need something like for example:

    override public function toString(...args):String {
    	return super.toString("path=" + _path, "size=" + _size);
    }

    So only the BasicClass needs to have the getQualifiedClassName… code in it.

  3. September 11th, 2008 at 21:46 | #3

    Hey, besides the (expensive) RegExp you could also do this:

    var name: String = getQualifiedClassName(obj);
    name = name.substring( name.lastIndexOf( ‘::’ ) + 2 );

  4. September 11th, 2008 at 21:53 | #4

    Hi Joa, yes I had that method in mind too. the question is: what is more expensive? substring() or match()? I keep hearing from all sides that regExp’s are more fast, powerful and generally being the next best thing to sliced bread. So I went with that. ;)

  5. tony
    October 4th, 2008 at 01:18 | #5

    Hey, that is some great and helpful stuff. Does just what I needed. I will put it to immediate use and thanks. Bythe way, I would think a search for text in a string would have to be faster than the regular expression, but I don’t think performance-wise anyone will notice either way. Thanks again and take care.

  6. October 4th, 2008 at 02:10 | #6

    hey tony. sure you could do that too with lastIndexOf as Joa said … but where would be then fun in that?! … i.e. I just wanted to make myself more familiar with RegExp’s. Then again tostring methods aren’t the kind of stuff that need to provide a lot of performance, but hey, choose what you like. :)

  7. tony
    October 4th, 2008 at 05:11 | #7

    You are right that regexps are more fun and also very handy to know. Anyway, I had to find out if there was a performance difference and ran a test. As expected, because the regular expressions are much more powerful than a plain search, they are also much slower. I ran each way in a tight loop 10,000 times and the regular expression method takes 120 times longer. If you are only doing a few dozen regex matches, no one would notice, but where performance is key and the matching is simple, avoid regex. They are mostly useful for very complex expressions that you cannot easily search for using simple methods. Anyway, great work on the toString override. I needed it and would never have come up with that myself.

  8. October 4th, 2008 at 12:32 | #8

    Thanks for the info tony! I wasn’t sure but it’s good to know that!

  9. igor
    October 16th, 2008 at 10:39 | #9

    Object.prototype.toString = function() {
    var r:String = “[” + getQualifiedClassName(this).match(“[^:]*$”)[0];
    if (this.name)
    r += ” name =”” + this.name + “” “;
    r += “]”
    return r;
    }

    Object.toString() is dynamic so it works for most of classes

  10. Rick R
    January 21st, 2010 at 04:50 | #10

    I’m new to AS coming over from Java/Groovy. Does AS have some convenient reflection API? I’d prefer my class toString introspect my class properties and dump them out as well.

    In a groovy class I can just do:

    @Override
    String toString() {
    def props = this.properties
    String s = props["class"].getName()+”: ”
    //you don’t want to see these in toString:
    props.remove(“class”)
    props.remove(“metaClass”)
    return s + props
    }

    The above will use reflection to dump out all my class properties MyCLass: foo = boo, doo = a, etc

  11. January 21st, 2010 at 12:26 | #11

    @Rick check out the describeType function in the flash.utils package http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html#describeType%28%29

  1. No trackbacks yet.
You must be logged in to post a comment.