AS3 - 使用实际类名的参数化工厂方法

而不是使用硬编码的switch语句,在其中传递类的字符串名称,然后实例化相应的类,我想将类的实际名称传递给我的工厂方法,并让它动态创建一个实例那个班。我认为这将是微不足道的,我很惊讶它不起作用。我必须遗漏一些非常基本的东西: 示例代码:
createProduct(50, "Product1Class");
createProduct(5, "Product2Class");


private function createProduct(amount:uint, productClassName:String):void {
    var productReference:Class;
    try {
        productReference = getDefinitionByName(productClassName) as Class;

        for (var i:uint = 0; i < amount; i++) {
        var product = new productReference() as ProductBaseClass; // throws reference error!
        }
    } catch (error:ReferenceError) {
        throw new ReferenceError(error.message + " Have you linked a library item to this class?");
    }
 }
唯一可能有点奇怪(不确定)的是这些“产品”实际上是链接的库项目(即:我在库中有一个movieClip,它与Product1Class有联系,另一个到Product2Class,它们都扩展了ProductBaseClass,而这又扩展了MovieClip。 为什么引用ReferenceError?     
已邀请:
如果您有一个运行时加载的库,那么Class不会被编译到主swf中,因此当您尝试创建它们时会收到运行时引用错误。 要解决此问题,您可以声明要编译的类的“虚拟”变量,或者如果使用flex编译器,则可以选择包含您缺少的类。 例如在项目的任何地方声明这些
private var p1:Product1Class;
private var p2:Product2Class;
这是一个令人沮丧的问题,如果您的类扩展了MovieClip,这是一个动态类,您可以通过执行以下操作来访问属性等:
var product:MovieClip = new productReference() as MovieClip;
p1["someCustomProperty"]; //Dot notation might work here as it is a dynamic class
    
Chris是绝对正确的,在调用
getDefinitionByName
时实际上抛出了ReferenceError,这意味着反射方法在您的应用程序域中找不到
Product1Class
Product2Class
。您可以通过直接检查应用程序域来检查定义是否可用,例如:
// inside your createProduct method, yields 'false'.
ApplicationDomain.currentDomain.hasDefinition( productClassName );
这些库资产是否在运行时加载?如果是这样,您可以通过向Loader添加适当配置的
LoaderContext
来确保库swf已加载到当前应用程序域中,或者您可以使用加载的swf的应用程序域的
getDefinition
方法替换对
getDefinitionByName
的调用。     
getDefinitionByName()和ApplicationDomain.currentDomain.hasDefinition()需要完全限定的类名。当Product1Class和Product2Class在默认包中时,原始帖子中的示例代码有效。但是,如果将产品类移动到另一个包,则必须确保为getDefinitionByName()提供完全限定的类名。 因此,如果我们将产品类放在com.example.products中,那么调用将变为:
productReference = getDefinitionByName("com.example.products.Product1Class") as Class;
我不太确定这种动态工厂类的最佳实践是什么,但我最终做的(因为所有产品都在同一个包中)是在我的工厂类中创建一个常量来定义我的包产品:
private const PRODUCT_PACKAGE:String = "com.example.products."; // note the trailing period
因此,您的客户端代码不需要知道(也不定义)产品包。使用getDefinitionByName()时,只需将此常量添加到产品类名称中。     

要回复问题请先登录注册