-->

When using the 'Class' datatype, how can I

2019-08-29 23:27发布

问题:

I've got a method that accepts a parameter of type Class, and I want to only accept classes that extend SuperClass. Right now, all I can figure out to do is this, which does a run-time check on an instance:

public function careless(SomeClass:Class):void {
    var instance:SomeClass = new SomeClass();
    if (instance as SuperClass) {
        // great, i guess
    } else {
        // damn, wish i'd have known this at compile time
    }

}

Is there any way to do something like this, so I can be assured that a Class instance extends some super class?

public function careful(SomeClass:[Class extends SuperClass]):void {
    var instance:SuperClass = new SomeClass();
    // all is good
}

回答1:

If you are going to instantiate it anyway, why not accept an object instead which allows you to type it to :SuperClass?

careless(SomeClass);
//vs.
careless(new SomeClass);

Not too much of a problem there as far as your code goes. There are a few differences though:

  • The object has to be created, because an object is required. If your function does not instantiate the class under some circumstances, this can be a problem. Additional logic to pass either an object or null can bloat the function call.
  • If you cannot call the constructor outside that function, it won't work either.

All that is solved by the factory pattern. Pass a factory as the parameter that produces SuperClass objects.

function careful(factory:SuperClassFactory)


回答2:

Your requirements:

I want to only accept classes that extend SuperClass

and

I need to pass in a Class so that it can be instantiated many times by other objects later

Can be met by passing in an instance of the class you need, and using the Object.constructor() method.

public function careful(someInstance:SuperClass):void {
    //you probably want to store classRef in a member variable
    var classRef: Class = someInstance.constructor();

    //the following is guaranteed to cast correctly,
    //since someInstance will always be a descendant of SuperClass  
    var myInst:SuperClass = new classRef() as SuperClass; 
}

More reading here.



回答3:

You can't do that in ActionScript 3. In languages like C# you can do something like (forgive me if the syntax is off):

public void Careless<T>() where T : SuperClass

But AS3 does not have 'generics'. Unfortunately the only way I know how to do what you want is the way you have already done.

A pattern that might be more suitable for your use case might be something like:

class SuperClass
{
    public static function careless():void
    {
       var instance:SuperClass = new SuperClass();

       // ...
    }
}

The only way to have static type checking in ActionScript 3 is to provide an instance of a class.



回答4:

It is possible but it's expensive. You can use on a Class (not instance) the:

flash.utils.describeType

You then get an XML with a bunch of information including inheritance for that class. Like I said it's an expensive process and probably creating an instance and checking it will be in most cases faster.