Нарядная инициализация AS1 классов.
Для начала хочется прибить читателя кодом:
#initclip
this.set$$$Class = function() {
delete this.set$$$Class;
var $$$Class = _global.$$$=function () {
this.init();
};
Object.registerClass(‘$$$_mc’, $$$Class);
ASSetPropFlags(_global, “$$$”, 7, 1);
var tmp = $$$Class.prototype=new MovieClip();
tmp.init = function() {
};
};
this.set$$$Class();
#endinitclip
- не правда ли, странный код? Как думаете, сколько времени у меня ушло на его написание? Доли секунды. Во флэше, когда курсор на редакторе кода, я последовательно нажал три клавиши: Esc+s+c и получил этот код.
Не стоит пока пытаться повторить этот подвиг.
Чтобы фокус удался, нам нужно задать эскейп-последовательность.
Задаем эскейп-последовательность
Для начала нужно провести небольшие манипуляции с файлом ActionsPanel.xml.
Он лежит в папочке C:\Documents and Settings\ИмяЮзера\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\ActionsPanel\
- разумеется ИмяЮзера это ваше имя пользователя на этом компе.
Итак, открываем (не ленимся!) ActionsPanel.xml и практически вначале, после строки
<folder name="Global Functions" id="Actions"........................
втыкаем следующий XML узел:
<folder name="Personal" id="Personal" tiptext="Presonal" helpid="">
<action name="setClass" tiptext="setClass" helpid="" text="#initclip\nthis.set$$$Class = function() {\n
delete this.set$$$Class;\n var $$$Class = _global.$$$ = function () {\n this.init();\n };\n Object.registerClass(‘$$$_mc’, $$$Class);\n
ASSetPropFlags(_global, ‘$$$’, 7, 1);\n var tmp = $$$Class.prototype=new MovieClip();\n tmp.init = function() {\n };\n};\nthis.set$$$Class();\n
#endinitclip" quickey="sc"/>
</folder>
Сохраняем XML, перезапускаем редактор Flash. Всё. Ескейп-последовательность добавлена.
Теперь, при последовательном наботе Esc+s+c в окне редактора вставится заготовка класса.
Дальше-проще. Например мы хотим создать знаменитый по всем детским учебникам класс Ball.
Жмем Ctrl+h (поиск и замена). Водим $$$ вверху и Ball внизу. Получаем результат:
#initclip
this.setBallClass = function() {
delete this.setBallClass;
var BallClass = _global.Ball = function () {
this.init();
};
Object.registerClass(‘Ball_mc’, BallClass);
ASSetPropFlags(_global, ‘Ball’, 7, 1);
var tmp = BallClass.prototype=new MovieClip();
tmp.init = function() {
};
};
this.setBallClass();
#endinitclip
Теперь, собственно, можно приступить к изучению того, что мы натворили.
Приватные объекты
Первое и главное: Класс задается внутри метода-инициализатора класса, в данном случае это setBallClass. Этот метод удаляет ссылку на себя во время вызова, чтобы небыло лишнего мусора.
Однако, сам метод не удаляется, он остается жить в памяти, вечная ему память за это!
Зачем такие замороки? Это позволит нам иметь приватные, т.е недоступные снаружи переменные, объекты и методы.
Для дальнейших экспериментов модифицируем класс, снесем #initclip и #endinitclip,
сделаем класс наследником Object, соответственно удалим registerClass.
Затем добавим локальную переменную my_array и присвоим ей ссылку на массив.
Сделаем внутри метода init вызов trace с использованием ссылки на массив.
И в конце создадим экземпляр класса. Получим результат:
Забиваем Сайты В ТОП КУВАЛДОЙ - Уникальные возможности от SeoHammer
Каждая ссылка анализируется по трем пакетам оценки:
SEO, Трафик и SMM.
SeoHammer делает продвижение сайта прозрачным и простым занятием.
Ссылки, вечные ссылки, статьи, упоминания, пресс-релизы - используйте по максимуму потенциал SeoHammer для продвижения вашего сайта.
Что умеет делать SeoHammer
— Продвижение в один клик, интеллектуальный подбор запросов, покупка самых лучших ссылок с высокой степенью качества у лучших бирж ссылок.
— Регулярная проверка качества ссылок по более чем 100 показателям и ежедневный пересчет показателей качества проекта.
— Все известные форматы ссылок: арендные ссылки, вечные ссылки, публикации (упоминания, мнения, отзывы, статьи, пресс-релизы).
— SeoHammer покажет, где рост или падение, а также запросы, на которые нужно обратить внимание.
SeoHammer еще предоставляет технологию
Буст, она ускоряет продвижение в десятки раз,
а первые результаты появляются уже в течение первых 7 дней.
Зарегистрироваться и Начать продвижение
this.setBallClass = function() {
delete this.setBallClass;
var BallClass = _global.Ball=function () {
this.init();
};
ASSetPropFlags(_global, ‘Ball’, 7, 1);
var tmp = BallClass.prototype={};
var my_array = ["Hello, ", "world!"];
tmp.init = function() {
trace(my_array[0]+my_array[1]);
};
};
this.setBallClass();
// TEST
foo = new Ball()// Hello, world!
Самое время заглянуть в листинг переменных. Ничего кроме созданного экземпляра класса мы не увидим.
_global.Ball закрыт с помощью ASSetPropFlags,
а массив my_array хоть и существует в памяти, но добраться до него невозможно,
иначе, как из методов класса Ball.
Вот вам и приватность. Это ооочень удобно. Правильная организация приватных/публичных объектов,
когда у класса не торчат лишние уши, это здорово!
Эти уши никакой другой класс или объект случайно никогда не чикнет.
И к приватным объектам очень удобно обращаться: не нужно соображать по какому пути они находятся,
они локальны и доступны в любом месте кода класса.
Ссылки типа this.constructor легко заменяются на BallClass,
который объявлен как локальная переменная. Сылки this.__proto__ заменяются
на tmp.
Статические методы класса.
Сносим весь код, создаем мувик, обзываем его ball_mc,
задаем такой же Linkage, рисуем в нем квадратик (всем назло) и слоем выше жмем волшебную комбинацию клавиш:
Esc+s+c. Результат модифицируем ручками так, чтобы получилось следующее:
#initclip
this.setBallClass = function() {
delete this.setBallClass;
var BallClass = _global.Ball=function () {
this.init();
};
Object.registerClass(‘ball_mc’, BallClass);
ASSetPropFlags(_global, ‘Ball’, 7, 1);
var tmp = BallClass.prototype=new MovieClip();
tmp.max_width = 100;
tmp.max_height = 100;
var step = 2;
BallClass.create = function(thisObj, name, depth, initObj) {
var mc = thisObj.createEmptyMovieClip(name, depth);
mc.beginFill(0, 100),
mc.lineTo(10, 0), mc.lineTo(10, 10), mc.lineTo(0, 10),
mc.endFill();
for (var i in initObj) {
mc[i] = initObj[i];
}
mc.__proto__ = tmp;
BallClass.call(mc);
return mc;
};
var setDimentions = function () {
if ((this._width += step)>=this.max_width) {
this._width = this.max_width;
}
if ((this._height += step)>=this.max_height) {
this._height = this.max_height;
}
if (this._height == this.max_height && this._width == this.max_width) {
delete this.onEnterFrame;
}
};
tmp.init = function() {
this._width = this._height=1;
this.onEnterFrame = setDimentions;
};
};
this.setBallClass();
#endinitclip
- я понимаю, дураков нет корячиться - набивать самому, если можно просто скопировать.
Но совесть-то надо иметь. Если просят модифицировать ручками, надо модифицировать ручками, а не копировать.
Ок. бросаем на сцену мувик ball_mc и слоем выше втыкаем код:
Ball.create(this, "ball1_mc", 1, {_x:30, _y:50})
Тестируем, не верим своим глазам, восхищаемся результатом.
Мы создали статический метод, create, который нам может быть очень полезным, в случае,
когда предполагается, что данный класс может быть загружен извне динамически,
а объект класса будет использоваться в другом ролике.
В этом случае приаттачить мувик не удастся и нас спасет статический метод
create.
Параллельно предлагаю маленький тренинг:
Выяснилось, что нам не нужны max_width и max_height
в прототипе класса и Билл Гейтс дал указание сделать эти переменные приватными. Время пошло.
Ну как? Успели в отведенное время? За это вам повышена зарплата на $6000.
Не стоит благодарности.
Сервис онлайн-записи на собственном Telegram-боте
Попробуйте сервис онлайн-записи VisitTime на основе вашего собственного Telegram-бота:
— Разгрузит мастера, специалиста или компанию;
— Позволит гибко управлять расписанием и загрузкой;
— Разошлет оповещения о новых услугах или акциях;
— Позволит принять оплату на карту/кошелек/счет;
— Позволит записываться на групповые и персональные посещения;
— Поможет получить от клиента отзывы о визите к вам;
— Включает в себя сервис чаевых.
Для новых пользователей первый месяц бесплатно.
Зарегистрироваться в сервисе
Что еще? или подводные камни
Иногда, а скорее достаточно часто, требуется, чтобы класс, однажды инициализированный, не инициализировался заново.
Запросто. Просто добавим проверку на наличие класса:
#initclip
this.setBallClass = function() {
delete this.setBallClass;
if (_global.Ball) {
return
}
// код дальше....
};<.code>
второй момент, на который бы мне хотелось указать, это то, что локальные переменные можно объявлять когда угодно,
т.е. использовать до того, как они объявлены. В связи с этим не рекомендуется (особенно в отношении конструктора класса)
практика задания функций таким способом:
function myPrivateFunction (){
// code here
}
и настоятельно рекомендуется использование такого синтаксиса:
myPrivateFunction = function (){
// code here
}
Хотя эффект практически тот же, однако, в первом случае,
компилятор во время компиляции перемещает функцию со своего места на самый верх.
В итоге функция будет объявлена до кода:
if (_global.Ball) {
return
}
что в некоторых случаях может повлечь за собой неожиданные последствия.
Автор: Ivan Dembicki aka Iv.