__resolve
In AS2, the __resolve property is a really cool feature that allows you to do some pretty cool stuff. It is a property that can be set on any object (it needs to be set to a function to actually work), and in doing so you force the object to call that function whenever a property is requested from the object that is not defined (which is different than being set to undefined). This winds up being useful in a few situations. The first I’ll discuss is Symbols, then Keywords, and a makeshift variable name misspelling catcher. So here we go, I’m going to start kinda slow and proceed by trying to do something that most people probably have no interest in doing. As a side note, anyone interested in doing this sort of thing is AS3 needs to look into the Proxy object.
Say you want to create a variable. Easy,
var a=10;
Ok, now say you want to create two variables that point to the same thing. Well if you do
var a=10;
var b=a;
They are both set to 10, but if you do
a++;
Now a is 11 and b is still 10.
The problem is that numbers (as well as strings and booleans) are primitives; what we need is an object so we do
var a=new Object();
a.value=10;
var b=a;
a.value++;
Now magically a.value and b.value are both set to 11.
Ok, so now what I want to be able to do is have a way so that variable a actually points to b, not to the value that b is presently pointing at, but to b. This is where Symbols comes in. In Lisp and Scheme a symbol is an object that has a name and a value (in lisp it can also have a function, but we’re not going to get into that now). So if I want to have symbol A point at symbol B I just say:
(setf a 'b)
(setf b 20)
(print a) ;;prints the character B
(print (symbol-value a))
;; prints 20 since A evaluates to B and the value of B is 20
(print (eval a))
;; this does the exact same thing for the exact same reason
So in flash now I want to be able to write code that looks like this
Symbols.a.value=Symbols.b;
Symbols.b.value=10;
trace(Symbols.a.value) //traces [b]
trace(Symbols.b.value) //traces 10
Made it this far? Good. So to get this type of functionality I first need an class for a symbol. It needs to have a name, a value and a toString function so that when it traces it identifies itself instead of just outputting “[object Object]”. Here goes..
Symbol=function(name)
{
this.name=name;
this.value=null;
}
Symbol.prototype.toString=function()
{
return "["+this.name+"]";
}
Yeah, I still use the prototype method for creating classes because it rules. Maybe I’ll write a post about that sometime (one of the biggest reasons is that there’s a weird bug in the AS2 Class file method that has to do with closures not working correctly).
Now what we want is a way to create these symbols automatically so that we can just call Symbols.Hello and it will be there. This is where we use the magical __resolve property.
Symbols=new Object();
Symbols.__resolve=function(symbolName)
{
var newSymbol=new Symbol(symbolName);
Symbols[symbolName]=newSymbol;
return newSymbol;
}
The Symbols object gets created here, and then when we request a property from Symbols it either has it or it doesn’t, if it does it simply returns it, but if it isn’t there the function attached to the __resolve property is called with the parameter being the string representation of the property name you requested. We simply then create a new symbol with that string as the name, then we attach it as a property to Symbols, the property name being the name we’ve just requested.
And there you have it. Now we have Symbols in flash.
Keywords in Lisp are like symbols only they evaluate to themselves; that’s quite easy to do with the Symbol code above. I’ve had more need to be able to create strings automatically as if they are objects which is the code I’m going to show you here.
Keywords=new Object();
Keywords.__resolve=function(name)
{
return name;
}
This simply allows you to use object instead of strings for things like event names, library item names, etc. The nice thing about this is that if you use Keywords then instead of strings in your code and you have 1000 cases where you use Keywords.SomeThing and the string needs to change from “SomeThing” to “SomeThingElse” you can simply add the code
Keywords.SomeThing="SomethingElse";
And you’re done. (or you could do a find and replace but hey, we’re learning about __resolve now).
or as I mentioned with library items you could do something like this
Library=new Object();
Library.__resolve=function(name)
{
return name;
}
MovieClip.prototype.AttachItem=function(name)
{
var depth=this.getNextHighestDepth();
return this.attachMovie(name,name+depth,depth);
}
Then you can write code like
_root.AttachItem(Library.Button);
Lastly, as I mentioned before I enjoy writing my flash code without creating class files for it. This gives me a lot of extra freedom, but I don’t get the compiler checking my code to make sure that I’m not calling a variable that doesn’t exist which can sometimes cause some very difficult to track down bugs, especially when it’s late and your eyesight is shot. Here’s the code i use:
_global.__resolve=Object.prototype.__resolve=function(name)
{
trace("Error:requested undefined property "+name);
return undefined;
}
_root.__resolve=function(name)
{
return _global[name];
}
This traces out an error whenever a property is called that isn’t available just as a warning. This winds up being quite helpful for me during development, and then I remove it when finished. Technically, you’d think that you’d only need the Object.prototype.__resolve=… part, but it creates some problems with how flash works. Seems as though when you request something it first checks the _root for it, and then _global, and if it’s not found then it returns undefined. If you were to just set up the Object.prototype it would seem to work fine until you called
var arr=new Array();
Then it would tell you that Array is undefined since Array is not a value that’s defined in the _root, but actually in _global. Flash seems to check _root first, then _global, but if we set up just the Object.prototype it doesn’t, so we need to also set up _global (which oddly enough doesn’t extend Object), and then create a __resolve method on _root to check _global.
So there you have it, a bunch of stuff that’s interesting to know, but probably completely useless unless you’re doing something like, I don’t know, say writing a Lisp interpreter in flash.
Note:This is not the way that I implemented Symbols in the Lisp interpreter I posted here on the site. This concept is used in a new one that I’m working on that allows for full interoperability with Flash.
Comments
Post a comment