Question

class Test
{
    public var field1:SomeClass;
    public var field2:SomeClass = new SomeClass();
}

class Main
{
var test:Test = new Test();
    public static function start(){
        if(Test.field1 is SomeClass)
        {
            trace("yay!");
        }
        else if(Test.field1 is null)
        {
            trace("boo");
        }
        else
        {
            trace("None of those");
        }

        if(Test.field2 is SomeClass)
        {
            trace("yay!");
        }
        else if(Test.field2 is null)
        {
            trace("boo");
        }
        else
        {
            trace("None of those");
        }
    }   
}

Hi guys, in the above case the Main.start(); would return boo and yay! respectively, which means that there is no way to know what is the type intended for the field before it is initialized. The questions are: 1) Is there a way around this problem? 2) Maybe it is possible to do something like new Test.field1 and thus initialize it with intended class without specifying the actual class?

Was it helpful?

Solution

How to Not Define a Variable

public var field1; // this is a loosely typed variable.
public var field2:*; // this is an untyped variable.

You can use the * special type "when you want to defer type-checking to runtime. You can use an untyped property or expression to circumvent compile-time type checking in strict mode. Note, however, that runtime type checking of assignment statements occurs whether you use strict mode or not."

This is the same as implicitly declaring a datatype inside of an object or array.

var foo:Array = ["Apple", 123, true];

If you were to trace the type of each one, you'd see:

0:"Apple" (String)
1:123 (Number)
2:true (Boolean)

Each array value was implicitly defined at runtime when added to the array, rather than a predefined datatype.


How to know what type of Variable

The problem with is operator, is that the comparison will run up the chain of inheritance. If you had a bucket of Sprites, MovieClips, Objects, and Arrays, you might imagine a filter something like this:

function sortBucket(foo:*):void {
    if (foo is Object) {
        // put it in the object bucket
    } else if (foo is Array) {
        // put it in the array bucket
    } else if (foo is Sprite) {
        // put it in the sprite bucket
    } else if (foo is MovieClip) {
        // put it in the MovieClip bucket
    }
}

What you would find is that all foo would go into the first condition, being filtered into your "object bucket". This is because all Arrays, Sprites, and MovieClips inherit from Object and are therefore equal to one.

See the inheritance chart...

enter image description here

A more precise solution may be to use getQualifiedClassName(). Here's my solution below:

function getType(value:*):String {
    // Returns the type of object passed to it, as a string.
    var msg:String = flash.utils.getQualifiedClassName(value);
    if (msg.lastIndexOf("::") != -1) {msg = msg.split("::")[1];}
    return msg;
}

Now when presented with an untyped variable, getType() will return the implicit datatype stored. Here's the revised bucket sorter (that actually works) ...

function sortBucket(foo:*):void {
    switch (getType(foo)) {
        case "Object":
            // put it in the object bucket
            break;
        case "Array":
            // put it in the array bucket
            break;
        case "Sprite":
            // put it in the sprite bucket
            break;
        case "MovieClip":
            // put it in the MovieClip bucket
            break;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top