Quick AS3 tip that may be self-explanatory to most of you out there, yet stumped me for a while. In AS2, if you set a variable on your main timeline and wanted to access it from inside a movieclip, all you would need to do is call it by name. AS2 would then proceed up the scope chain looking for the variable by name. First, inside the movieclip, then on the parent of the movieclip (in this case…stage).
AS3 is a little different. Say you declare a variable on your main timeline like so:
var my_arr:Array = ["one", "two", "three", "four"];
Then you place a movieclip on your stage, and INSIDE your movieclip, you want to reference my_arr
(which is on the main timeline, or the movieclip’s parent). Back in AS2, you would simply type out my_arr
, and Flash would automagically find the variable as it searched the scope chain. In AS3, however, if you type this (again…inside the movieclip):
trace (my_arr);
or even trace(this.parent.my_arr);
You would get this error:
1119: Access of possibly undefined property my_arr through a reference with static type flash.display:DisplayObjectContainer.
Well, to avoid this little annoyance, you can try a strict coercion like so:
trace (MovieClip(this.parent).my_arr);
I wish I knew the exact reason as to why this behavior exists, but I do have my suspicions and theories in case you’re interested. What I believe is happening is that in AS3, the movieclip doesn’t want to assume it knows what its parent is. In fact, as far as it’s concerned, it only worries about whatever is in it, or “below” it (the concept is called encapsulation). Anything outside of it (or “above” it) is basically anybody’s guess and unless you specifically tell it “your parent is a movieclip,” it doesn’t make any assumptions.
Again, that’s my own theory – so if anyone out there knows the real reasons for this behavior (or even a better way of handling this) – let us know!
December 7th, 2008 at 6:48 pm
best tip ever.
December 8th, 2008 at 12:22 pm
The reason why flash throws an error when attempting to access
my_arr
in the first example is because the varparent
is assumed to be of the classDisplayObjectContainer
(whichSprite
,MovieClip
, etc all inherit from).DisplayObjectContainer
is a sealed class; meaning variables cannot be added to the class at runtime. That error indicates that no public variable namedmy_arr
is defined inDisplayObjectContainer
‘s class definition. (You can think of public vars as data that is accessible to the external world).The second example works because you are strong datatyping the variable
parent
to theMovieClip
class. TheMovieclip
class is a dynamic class, and accepts variables defined at runtime.The best practice would probably be to create a custom Document class whose class definition contains a public var named
my_arr
, and a custom class for your MovieClip as well. Something like so:// Code found in DocumentClass.as
package
{
public class DocumentClass
{
public var my_arr:Array = ["one","two","three"];
public function DocumentClass ( ):void
{
}
}
}
// Code found in MyMovieClip.as
.
{
public class MyMovieClip
{
public function MyMovieClip ( ):void
{
trace( [parent as DocumentClass].my_arr ); // prints: one,two,three
}
}
}
I’ve found that keeping all my code in external files really improves clarity and updatability in the long run.
Here’s more about Dynamic and Sealed classes. Lee Brimelow has a nice introduction tutorial about using the Document class. More on creating MovieClip that use and external class definition.
Hope that makes some sense
December 8th, 2008 at 11:41 pm
Hey Mark, thanks for clearing that up. I think it makes sense in my head. he,he,he. Do you use a doc class file for all your FLAs? I tend to skip external as files whenever I work on smaller projects.
December 13th, 2008 at 3:40 am
Hi everyone! (forgive my bad English).
I’m newbie in ActionScript and in programming in general.
The tip of this post fixed some problems I had. And I like too much of the ‘theoretical’ discussion here. The vast majority of the sites I found just throw off some ‘magical code’ that fix a problem and don’t care about the ‘logical foundations’ of the language.
Thank you!
December 16th, 2008 at 11:44 am
Hi David, I use external files with most small projects (though there are exceptions). I do so primarily so I have consistent code placement across all my projects, and because I use Textmate for actionscript editing and Flash’s built in editor drives me crazy
.
There are exceptions, for instance if I just need a quick script that doesn’t really interact with any other code, it makes sense to just throw it up on the timeline.
My philosophy though is do what works best for your own workflow. Examine what other people prefer, but in the end, go with what causes the least amount of pain
December 16th, 2008 at 12:46 pm
Wise counsel as always. I do prefer TextMate for AS editing, but I’m not well versed enough in the syntax to do away with code-hinting. I’m currently working on an external file, for example, and find myself writing a line of code in the IDE to get the code hinting, then copying it over to TextMate. (Incredibly inefficient I know, but I’m hoping this will help me rely more heavily on my brain, than the code-hinting…eventually).
February 5th, 2009 at 5:24 pm
The MovieClip(parent) syntax works for me in most cases but sometimes fails for reasons I just can’t figure out. In the same class I have the exact same line in multiple places. In one case it works (triggered by mouse event) in another it always returns null (in the init called from the parent). Why would this be the case? Is there anything I can do to the init function to force it to work? I’m at a total loss after hours of searching.
February 7th, 2009 at 7:05 pm
@al: I can’t say for sure but Mark’s explanation above makes some sense. Basically, if you’re trying to do anything to the DisplayObjectContainer, it will spit out an error because it is a sealed class. I wonder if in your class, parent sometimes refers to a displayObject, and others to its container. ? Anyone?
March 12th, 2009 at 1:25 pm
Wow this helped so much!
Thanks a bunch David!
Smccullo
March 16th, 2009 at 4:25 am
you are the best, thanks for your help.
July 29th, 2009 at 6:16 pm
thanks man.
July 29th, 2009 at 6:58 pm
I LOVE YOU
Thank you so, so, so, so, much!
This problem nearly blew my brains out!
October 16th, 2009 at 12:00 am
This one will work for sure
http://www.calypso88.com/?p=301
October 22nd, 2009 at 1:20 pm
Thanks dude. I used Main(this.parent.parent).my_var
to access a public variable set in my Main class from another class.
January 3rd, 2010 at 3:32 am
thnks a lot man! it worked perfect