On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru








 

ООП во флэш

Евгений Потапенко (ака john)

Данная небольшая статья рассказывает об объектной модели флэш. Уровень флэш-кодеров растет и, естественно, что есть желание программировать, используя объектно ориентированные приемы. Но информация об объектной модели флэш очень скудна (как и о JS, ксатати), и по этому вопросу есть много путаницы. Поэтому предоставляю вашему вниманию то понимание, которое сложилось у меня на данный момент. Так же хочу отметить, что все объекты флэш (Number, MovieClip, Sound, Mouse и так далее) так же используют объектную модель. Поэтому знание объектной модели флэш позволяет настраивать и создавать новые методы встроенных объектов флэш. Непосвещенному это будет казаться невероятным - 'самому менять акции???, непонял:'.

Итак, продолжим.

Суть объектной модели в Action Script (как и в JS) в том, что любой объект имеет ссылку на свой прототип, как бы 'лекало', содержание которого (параметры и методы) объект наследует.

Простой пример.

[CODE]

a = {} //создаем новый пустой объект.

a.__proto__ = {a:"a"} // вместо существующего прототипа подставляем новосозданный объект с параметром а равному строке 'а'.

b = {} // создаем второй объект.
b.__proto__ = a // в качестве прототипа подставляем первый объект.

trace(b.a) // делаем проверку на наличие параметра прототипа у второго объекта.

a.__proto__.a = "c" // меняем значение поля у прототипа первого объекта.

trace(b.a) // тестируем изменения во втором объекте.
[/CODE]

__proto__ - это ссылка на прототип объекта.

Если бы мы изменили поле у первого объекта, то мы бы смогли наблюдать полиморфизм и его наследование. То есть прототип первого объекта остался бы прежним, но значение одноименного поля у первого объекта изменилось. И это изменение тут же наследовал второй объект.

Вместо цепочки наследований можно делать деревья со сложной структурой, когда поля и методы одного объекта наследуют сразу несколько объектов.

Остановимся на механизме наследования. Важно понять, что методы и параметры объектов не копируются из прототипа. Просто при работе с объектом происходит поиск вызываемого параметра или метода. Поиск производится как в параметрах и методах самого объекта, так и в полях прототипа (а также в прототипе прототипа, и так далее). Это происходит всегда. Только чаще прототип пуст и его полей мы не видим. Поэтому как только мы меняем объект-прототип, мы меняем объекты-наследники.

Второй момент объектной модели флэша, который нужно понять, это работа с конструкторами. Хоть в нашем предыдущем примере мы обошлись без конструктора, конструктор был задействован автоматически.

Конструктор - это функция. Любая функция во флэш может быть использована в качестве конструктора.

Используя конструкцию данного вида, мы создаем новый объект.

[CODE]
any_new_object = new constrictor_name();
[/CODE]

Мы, не задумываясь, используем данную конструкцию, создавая массивы например.

Любая функция имеет ссылку на некий объект, который будет прототипом для объектов, которые будут созданы функцией. Изначально данный объект пуст. Изменяя его или подставляя уже готовый объект, мы сможем создавать объекты с нужным прототипом.

[CODE]
//*************************************************************************
function constructor_one()
{
this.a = "a"
this.b = "b"
this.method = function()
{
trace("one")
}
}
//*************************************************************************
one = new constructor_one();

[/CODE]

Мы создали объект с пустым прототипом с двумя полями и одним методом.

Теперь изменим прототип конструктора.

[CODE]
constructor_one.prototype.new_param = "new_param";
[/CODE]

Создадим второй объект.
[CODE]
two = new constructor_one();
trace(two.new_param) // трейсится 'new_param'
[/CODE]

Второй объект имеет дополнительный параметр 'new_param', наследованный от прототипа.
Проверяем первый объект на наличие нового поля и убеждаемся что оно также присуствует.

Мы так же можем не просто модифицировать прототип конструктора, но и подставлять его на готовые объекты. Но наследоваться новые прототипы будут только в новосоздаваемых объектах.

Попробуем сделать подмену прототипа у конструктора. Вернемся к моменту когда был создан первый объект

[CODE]
function constructor_one()
{
this.a = "a"
this.b = "b"
this.method = function()
{
trace("one")
}
}
//*************************************************************************
one = new constructor_one();

constructor_one.prototype = {param:'any_value'}; // делаем подмену прототипа
[/CODE]

Создадим второй объект. И проверим первый и второй объект на наличие параметра 'param'.

[CODE]
two = new constructor_one();
trace(one.param)
trace(two.param)
[/CODE]

Первый объект имеет то же количество полей, что и при создании. И поля 'param' он не имеет.

Почему же изменяя прототип конструктора созданные до этого объекты наследуют изменения, а при подмене нет? Все просто. В первом случае мы модифицируем объект, на который имеют ссылку все новосозданые объекты и конструктор. При подмене же конструктор уже имеет ссылку на другой объект-прототип и ничего уже существующими объектам не наследуется. Казалось бы элементарно, но эта тонкость создает путаницу у начинающих.

Повторюсь. Передача ссылки на объект-прототип от конструктора к создаваемогу объекту происходит в момент создания объекта.

Чтобы 'синхронизировать' прототипы двух созданных нами объектов, нам нужно скопировать ссылку с прототипа второго объекта на первый объект.

[CODE]
one.__proto__ = two.__proto__;
[/CODE]

Такой вопрос. Где лучше создавать методы и параметры объектов. В прототипах или в конструкторах. Ответ - в прототипах. Методы и параметры не дублируются в каждом объекте. Их легче менять и не тратится лишняя память.

Для работы с объектами и с прототипами у нас есть еще одно ключевое слово constructor. Мы можем им пользоваться, например, тогда когда мы не знаем какой конструктор у объекта, и мы хотим создать другой объект, используя тот же конструктор.

[CODE]
three = new two.constructor();
[/CODE]

И естественно, есть ключевое слово this. Но я думаю, если вы читаете данную статью, вам значение данного слова объяснять не нужно.

А как же 'менять акции???'. Очено просто. Обращаться к встроенным объектам, к их прототипам и менять то что нужно.

Простой пример меняющий акцию 'play' на 'stop', и наоборот.

[CODE]
MovieClip.prototype.stop_old = MovieClip.prototype.stop;
MovieClip.prototype.play_old = MovieClip.prototype.play;

MovieClip.prototype.stop = MovieClip.prototype.play_old;
MovieClip.prototype.play = MovieClip.prototype.stop_old;
[/CODE]

А вот классный приметр который убыстряет работу метода split объекта String почти в десять раз:

[CODE]

st.OldSplit = st.split;//Creat Link to old split function

//*************************************************************************
st.split = function(str)
{ //Creat new split function

if(str.length>1)return this.OldSplit(str);

if (str == "" || str == null) return this.toCharArray();

var result = new Array();
var d = this.length;
var n = 0;
var tmpStr = "";
var ch;

while(n<d)
{
//ch = this.charAt(n++);
ch = substring(this ,++n, 1);
if(ch==str)
{
result.push(tmpStr);
tmpStr="";
}else{
tmpStr += ch;
}

}
result.push(tmpStr);
return result;
}
//*************************************************************************
st.toCharArray = function()
{
var st = this;
var arr_result = new Array();
for (var s=0;s < st.length;s++)
{
arr_result.push(substring(this, s+1, 1));
}
return arr_result;
}
[/CODE]

И так до победного конца.

Удачи.



Литература по FLASH