AS3 - Параметризованный фабричный метод с использованием фактического имени класса - PullRequest
1 голос
/ 05 января 2011

Вместо того, чтобы использовать жестко запрограммированный оператор 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?");
    }
 }

Единственное, что может быть немного странным (не уверен), это то, что эти "продукты" на самом деле являются связанными элементами библиотеки (то есть: у меня есть мувиклип в библиотеке, который имеет связь с Product1Class, а другой - с Product2Class, оба из которых расширение ProductBaseClass, которое, в свою очередь, расширяет MovieClip.

Почему ReferenceError?

Ответы [ 3 ]

1 голос
/ 06 января 2011

Крис абсолютно прав, на самом деле ReferenceError выбрасывается во время вызова getDefinitionByName, что означает, что метод отражения не может найти Product1Class или Product2Class в вашей области приложения.Вы всегда можете проверить, доступно ли определение, проверив домен приложения напрямую, например:

// inside your createProduct method, yields 'false'.
ApplicationDomain.currentDomain.hasDefinition( productClassName );

Загружаются ли эти библиотечные активы во время выполнения?Если это так, вы можете убедиться, что библиотека swf загружена в текущий домен приложения, добавив соответствующим образом настроенный LoaderContext в ваш загрузчик, или вы можете заменить вызов getDefinitionByName на загруженный файл приложения swf getDefinitionметод.

1 голос
/ 09 января 2011

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 ().

1 голос
/ 05 января 2011

Если у вас есть загруженная во время выполнения библиотека, то классы не компилируются в основной 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...