3.8 ActionScript 2.0 Type Checking Gotchas

 <  Day Day Up  >  

ActionScript 2.0's type checking system has its quirks and limitations. The remainder of this chapter covers some anomalies to keep in mind when working with ActionScript 2.0.

3.8.1 Global Variables Can't Be Typed

To create a global variable in ActionScript, we add a property to the _global object, as follows :

 _global.   varname   =   value   ; 

The preceding property-definition syntax is a carryover from ActionScript 1.0 and does not support datatype declarations. It is, therefore, impossible to use type checking with a global variable. For example, this causes a compile-time syntax error:

 _global.author:String = "moock";  // Output panel displays: Syntax error. 

As an alternative, you should consider using a class property in lieu of globals , as discussed under "Property Attributes" in Chapter 4.

3.8.2 Type Checking and Timeline Code

When code is placed on a frame in a timeline, the properties and methods of movie clips are not type checked. For example, the following attempt to assign a String value to the numeric property _y does not generate a compile-time type mismatch error when the code is placed on a frame in a timeline:

 _root._y = "test";  // No error. (Should be a type mismatch error.) 

Similarly, the following attempt to store a number returned by getBytesLoaded( ) in a String variable does not generate an error when the code is placed on a frame:

 // No error. (Should be a type mismatch error.) var msg:String = _root.getBytesLoaded( ); 

Furthermore, assigning the current MovieClip instance ( this ) to a non- MovieClip variable or passing the current MovieClip instance ( this ) to a non- MovieClip function parameter causes no error. For example, when placed on a frame in a timeline, the following examples yield no error:

 var x:String = this;  // No error. (Should be a type mismatch error.) function square(x:Number):Number {   return x * x; } square(this);  // No error. (Should be a type mismatch error.) 

These problems occur only within code on a frame in a timeline, because on a timeline, nested movie clips are treated as dynamic properties of the containing movie clip. ActionScript 2.0 does not type check dynamic properties. However, within an ActionScript 2.0 class, type checking works properly with MovieClip instances.

To ensure proper type checking for movie clips within timeline code, first assign the MovieClip instance in question to a variable of type MovieClip , and use that variable in place of the MovieClip instance reference. For example, this code generates type mismatch errors at compile time (remember, compile-time errors are your friend, so although this code generates errors, it demonstrates the proper way to achieve type checking in timeline code):

 var theRoot:MovieClip = _root; theRoot._y = "test";                        // Type mismatch error! var msg:String = theRoot.getBytesLoaded( );  // Type mismatch error! var thisMC:MovieClip = this; var x:String = thisMC;                      // Type mismatch error! function square(x:Number):Number {   return x * x; } square(thisMC);                             // Type mismatch error! 

3.8.3 Type Checking XML Instances

Unbeknownst to many developers, the built-in XML class is actually a subclass of the XMLNode class, which was undocumented by Macromedia until Flash MX 2004. Furthermore, all child nodes of an XML instance are instances of the XMLNode class, not of the XML class! The relationship between the XML and XMLNode classes can be a source of confusion when working with ActionScript 2.0's type checking. The following code demonstrates the issue. It creates a new XML instance, stores the instance in a variable, xmlDoc , then attempts to assign one of its child nodes to a new variable, xmlFragment :

 var xmlDoc:XML = new XML("<P>Hello world</P>"); var xmlFragment:XML = xmlDoc.firstChild;  // Error. 

The preceding code causes a type mismatch error because xmlDoc.firstChild is an XMLNode instance, not an XML instance. To fix the error, we simply declare the datatype of xmlFragment as XMLNode instead of XML (change shown in bold):

 var xmlDoc:XML = new XML("<P>Hello world</P>"); var xmlFragment  :XMLNode  = xmlDoc.firstChild;  // No error 

The preceding code does not cause a type mismatch error because ”as we learned earlier under "Compatible Types" ”the compiler knows that every XML instance has, through inheritance, all the properties and methods of the XMLNode class (remember that the XML class is a subclass of the XMLNode class despite their names , which might imply the opposite ).

In general, when you want a variable to store an XML instance or any of its children, you should set the variable's datatype to XMLNode .

3.8.4 No Type Checking with the [] Operator

When a property or method is accessed via the [] operator, the compiler does not perform type checking. For example, the following code attempts to execute a nonexistent method. No error occurs when the method is accessed via the [] operator:

 var d:Date = new Date( ); d["noSuchMethod"]( );  // No compile-time error, but fails                        // silently at runtime. d.noSuchMethod( );     // Compile-time error. 

Similarly, the following code mistakenly attempts to store a String property ( name_txt.text ) in a Number variable ( userID ). No error occurs when the property is accessed via the [] operator:

 target_mc.createTextField("tf", 0, 0, 0, 400, 400); var name_txt:TextField = target_mc.tf; name_txt.border = true; name_txt.text = "Type your name..."; var userID:Number = name_txt["text"];  // No error. At runtime,   userID   // stores a string value. var userID:Number = name_txt.text;     // Compile-time error. 

Therefore, to take advantage of type checking, you should rewrite any old code that uses the [] operator to access methods or properties. Use the dot operator (a period) instead of [] , as is a best practice in ActionScript 2.0 regardless, unless you're dynamically generating the name of a property or method. Although the lack of type checking when using the [] operator might seem an oversight, it is necessary because it allows access to properties and methods whose names are determined dynamically at runtime.

3.8.5 Array Elements and Type Checking

In other object-oriented languages, the canonical example of casting portrays a programmer retrieving an object from an array of objects whose types are unknown and casting that object to a known type.

For example, here we have an XML instance:

 var doc:XML = new XML("<P>hello world</P"); 

Suppose we store that XML instance in an array, like this:

 var items:Array = new Array( ); items.push(doc); 

Because the array, items , does not keep track of the datatypes of its elements, the following code should generate a type mismatch error:

 var otherDoc:XML = items[0]; 

The programmer knows that the element items[0] is an XML instance, but the compiler doesn't recognize this fact. Rather, the compiler treats each array element as a generic Object . The sensible solution here is to cast the value items[0] to the XML datatype:

 var otherDoc:XML = XML(items[0]); 

However, even without that cast, the code generates no errors at compile time. Why not? Because, as we learned in the previous section, the compiler skips type checking for values accessed with the [] operator.

The compiler also generates no errors when accessing nonexistent properties and methods on an array's elements. For example, this code generates no error even though neither the XML class nor the Object class defines the method fixAllBugs( ) .

 items[0].fixAllBugs( );  // No error. 

This unfortunate lack of error messages means that you must effectively type check all objects used through array elements yourself. Remember to be extra careful when working with arrays.

 <  Day Day Up  >  


Essential ActionScript 2.0
Essential ActionScript 2.0
ISBN: 0596006527
EAN: 2147483647
Year: 2004
Pages: 177
Authors: Colin Moock

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net