В этом уроке рассмотрим, как создать ссылку на класс из строкового выражения, а затем как создать экземпляр этого класса, используя встроенную в ActionScript 3 функцию getDefinitionByName(). Вы также узнаете какие способы решения лучше использовать в различных ситуациях, если возникает ошибка при компиляции кода с этой функцией.
В чем польза функции getDefinitionByName()?
Функция getDefinitionByName()
очень полезна, если вам нужно создать новые экземпляры из различных классов с использованием строкового значения. Например, если у вас есть семь различных тайлов, которые представлены классами Tile1
, Tile2
и т.д., и нужно создать экземпляры на их основе, то необходимо будет написать следующий код:
private function createTiles():void
{
var tile1:Tile1 = new Tile1();
var tile2:Tile2 = new Tile2();
var tile3:Tile3 = new Tile3();
var tile4:Tile4 = new Tile4();
var tile5:Tile5 = new Tile5();
var tile6:Tile6 = new Tile6();
var tile7:Tile7 = new Tile7();
stage.addChild( tile1 );
stage.addChild( tile2 );
stage.addChild( tile3 );
// Действительно, так много строк кода!
}
Функция getDefinitionByName() позволяет решить эту проблему.
Как использовать функцию getDefinitionByName() в ActionScript 3?
Итак, код, представленный выше, немного «захламленный» так как записано много строк просто для того, чтобы создать немного различные тайлы. А вот как можно достичь того же самого результата при помощи функции getDefinitionByName()
:
private function createTiles():void
{
for( var i:int = 1; i < 8; i++ )
{
var tileRef:Class = getDefinitionByName( "Tile" + i ) as Class;
var tile:Sprite = new tileRef();
stage.addChild( tile );
}
}
В строчке 6 функция getDefinitionByName() возвращает ссылку на класс с именем «Tile + текущее значение переменной i в цикле». Итак, когда переменная i равна 1, функция getDefinitionByName("Tile" + i);
возвращает ссылку на класс Tile1
. Затем создаем тайл и добавляем его на сцену.
Примечание: обратите внимание, что мы не можем написать var tile:tileRef потому что tileRef не ссылается на что-либо во время компиляции, а если вы попытаетесь, то произойдет ошибка компилятора.
Тем не менее, при запуске кода, он не будет работать! Вы получите сообщение об ошибке «variable is undefined», в большинстве случаев, потому что о классе «Tile1» может быть недостаточно информации для AdobeFlash чтобы найти этот класс. Давайте рассмотрим некоторые способы решения этой проблемы.
Решение проблемы с функцией getDefinitionByName()
Есть несколько часто используемых способов решить проблему с переменной, когда выходит сообщение о неизвестной ошибке при запуске кода в примере выше. Давайте посмотрим, как это можно сделать.
Вот несколько способов решить проблему с ошибкой при использовании функции getDefinitionByName()
:
- Использовать пустой переменной
- Использовать краткое описание имени класса
- Включать полный путь класса в строковую переменную
- Включать SWC-файл с классом в проекте
Использование пустой переменной
При этом способе вы просто создаете некоторые пустые неиспользуемые переменные со ссылками на те классы, которые затем будете использовать с функцией getDefinitionByName()
.
private var dummyTile1:Tile1;
private var dummyTile2:Tile2;
//и т.д.
private function createTiles():void
{
//Создаем тайлы
}
Данный код работает, но выглядит некрасиво. Если у вас есть классы Tile в другом пакете, то нужно будет импортировать их.
Краткое описание имени класса
Это тоже самое, что и способ с пустой переменной, но не нужно беспокоится над установкой переменной для каждого класса, а просто нужно поместить несколько явных ссылок на эти классы.
Tile1;Tile2;Tile3;Tile4;Tile5;Tile6;Tile7;
//и т.д.
private function createTiles():void
{
//Создаем тайлы
}
Теперь код выглядит немного аккуратнее, но придется обновлять этот список каждый раз при создании нового тайла.
Включение полного пути класса в строковую переменную
Еще один способ, который намного аккуратнее (если у вас есть классы в другом пакете) это включить полный путь имени в строку для функции getDefinitionByName()
:
//Предположим, что все классы Tiles находятся в пакете 'project.Tiles'
private function createTiles():void
{
for( var i:int = 1; i < 8; i++ )
{
var tileRef:Class = getDefinitionByName( "project.Tiles.Tile" + i ) as Class;
var tile:tileRef = new tileRef();
stage.addChild( tile );
}
}
Намного опрятнее! Тем не менее, этот код работает только, если классы находятся в отдельном пакете от данного класса.
Использование библиотеки SWC
Если тайлы содержатся в файле SWC, то вы можете использовать наиболее легкий способ, без необходимости использовать импорт или пустые переменные. Этот способ нужно использовать следующим образом:
В свойствах проекта выбрать «ActionScript Compiler»
В поле «Additional compiler arguments» добавить строчку: include-libraries PATH_TO_SWC
Путь PATH_TO_SWC должен быть абсолютным, а не относительным, т.е. указывать точное расположение файла.
Хорошо, большинство этих способов уже были объяснены. К сожалению, нет каких-то волшебных способов для решения проблемы с появлением сообщения об ошибке при компиляции, если у вас все тайлы в одном пакете, также как и все другие файлы ActionScript. Я бы порекомендовал создать новый пакет с именем Tiles, например, если вы хотите использовать эти способы решения проблемы с появлением ошибки, возникающей при использовании функции getDefinitionByName()
.
Ну, вы только что узнали, как использовать функцию getDefinitionByName()
и самые лучшие способы решения проблемы с ошибкой при компиляции. Надеюсь, что урок поможет вам в дальнейших проектах, и если у вас есть какие-то вопросы, то задавайте их в комментариях. Также если урок был полезен — добавьте его в закладки социальных сетей (значки внизу), это поможет продвижению сайта.
А что это за запись такая Tile1;Tile2;Tile3;Tile4;Tile5;Tile6;Tile7; ?Какое то перечисление? вообще не понятно в этом примере для чего так писать нужно.
Это так называемый «импорт классов», а если точнее, то это объявление переменных. Компилятор flash при компиляции включает те классы, которые явно указаны в коде.
В примере не используется явное описание использования классов:
var tile1:Tile1 = new Tile1();
var tile2:Tile2 = new Tile2();
Поэтому компилятор в данном примере не принимает к сведению неявно указанные классы во время выполнения кода.
Но так как мы объявили неописанные переменные указанных типов, то компилятор произведет импорт данных классов при компиляции. Можно было просто указать обычным импортом, чтобы компилятор «знал», что эти классы будут использоваться в коде.
Интересная статья, думаю стоит добавить в избранное