How to properly test for class inheritance in Acti

2019-06-21 21:07发布

问题:

In ActionScript 3, you can figure out whether object O is of class C or of a class that extends or implements class C (directly or indirectly) using...

if (O is C) {
    ...
}

What I want to do is to test whether class CC extends or implements class C (directly or indirectly), without having to instantiate an object.

In Java, you would use...

if (C.isAssignableFrom (CC)) {
    ...
}

http://java.sun.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class)

How about ActionScript 3?

Thanks!

回答1:

You can call describeType() on CC directly. You do not have to instantiate the object.

var typeXML:XML = describeType(CC);
if(typeXML.factory.extendsClass.(@type=="C").length() > 0)
{
...

It's not as clean as I'd like but I can't find anything better.

(via Amarghosh: [http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html#describeType()][1] )



回答2:

I think , you will have to manually parse through the XML object returned by flash.utils.describeType



回答3:

Alternatively, if you use as3commons-reflect package (which is very, very useful, by the way), you can call:

ClassUtils.getImplementedInterfaces(CC)


回答4:

Worth including the Spicelib reflection library as another alternative. Specifically ClassInfo.isType.

Checks whether the class or interface represented by this ClassInfo instance is a subclass or subinterface of the specified class

ClassInfo.forClass(A).isType(B);


回答5:

Here's a hack I just found. Not sure how solid it is, but it works for me.

var child:Child = getChild() as Parent;
if(child != null) {
    ...
}


回答6:

describeType() is very slow, computationally speaking. If you need to determine the inheritance chain of uninstantiated classes, consider using Class.prototype and prototype.isPrototypeOf(). This allows you to check inheritance and equality if all you have are the Classes themselves (as opposed to an object that is an instance of that Class).

If you only have a String representation of the class name (as opposed to the Class itself), then you have to convert that to a proper Class first, using flash.utils.getDefinitionByName() assuming you have at least declared the class somewhere in your code. If the class only exists somewhere in a loaded SWF Library, you may have to use something like ApplicationDomain.currentDomain.getDefinitionByName() or contextLoader.currentDomain.getDefinitionByName().

Here's a working example that accepts either Classes or String class names and checks whether the first one is in the inheritance chain of the second one. The additional argument allows you to decide whether you want to return false if the two classes are identical rather than the first extending the second.

/**
 * Determines whether the childClass is in the inheritance chain of the parentClass. Both classes must be declared
 * within the current ApplicationDomain for this to work.
 * 
 * @param   childClass
 * @param   parentClass
 * @param   mustBeChild
 */
public static function inheritsFrom(childClass:*, parentClass:*, mustBeChild:Boolean = false) {
    var child:Class,
        parent:Class;

    if (childClass is Class) {
        child = childClass;
    } else if (childClass is String){
        child = getDefinitionByName(childClass) as Class;
    }

    if (! child) {
        throw new ArgumentError("childClass must be a valid class name or a Class");
    }

    if (parentClass is Class) {
        parent = parentClass;
    } else if (parentClass is String){
        parent = getDefinitionByName(parentClass) as Class;
    }

    if (! parent) {
        throw new ArgumentError("parentClass must be a valid class name or a Class");
    }

    if (parent.prototype.isPrototypeOf(child.prototype)) {
        return true;
    } else {
        if (mustBeChild) {
            return false;
        } else {
            if (parent.prototype === child.prototype) {
                return true;
            }
        }
    }

    return false;
}