Экземпляры и краткое описание оператора "New"
Определения |
Класс | (Class) | - шаблон, используемый для указания свойств объекта. |
Экземпляр | (Instance) | - объект, создаваемый с помощью класса. |
Связь классов и экземпляров с тем, что мы уже рассмотрели:
- Экземпляры (объекты) - реальные объекты, которые могут иметь свойства (например inst1.x имеет свойство x).
- Экземпляры можно рассматривать как контейнеры, классы - как описание объектов, помещаемых в контейнер.
- Экземпляры имеют ограниченную область действия и не "видят" ничего снаружи ... Скоро мы также рассмотрим подобную ситуацию с классами.
- Экземпляры создаются с помощью классов и эти понятия могут быть взаимосвязанными, но мы только начинаем знакомиться с этой темой...
В предыдущем разделе мы создали несколько новых объектов, и хотя всё это работало как нужно, действительно ли понимали, что и как происходит? Давайте перейдём к более детальному рассмотрению. Вот краткая версия нашего предыдущего кода (нумерация сделана только для удобства):
1) Template = function() 2) { 3) this.x = 5; 4) this.y = 7; 5) } 6) inst1 = new Template();
Каким образом получилось так, что inst1 заканчивается свойствами x и y? Откуда ActionScript знает, что это именно то, что нам нужно? Давайте разберём этот пример шаг за шагом. Первым делом определяется класс и это только описание, от него мало толку, пока его не вызвали. Первая строка, которая указывает на что-то конкретное - строка #6. Правая сторона уравнения всегда первична и рассматривается в первую очередь. Вот мы с неё и начнём. Слово new используется в разных случаях, но самое главное, зачем оно нам может понадобиться - создание нового объекта (поля, контейнера...) без свойств и имени. Потом оно отсылает этот объект к тому классу, на который указывает выражение, находящееся рядом с ним. В нашем примере это класс, с именем Template (Шаблон). Итак, правая часть уравнения в строке #6 отсылает "объект без свойств" к "Template".
Каждый класс, будучи вызванным, ожидает и получает пустой контейнер без имени. Этому контейнеру с началом блока кода временно присваивается имя this и затем он "проходит" через класс. Во время такого "прохождения" ему присваиваются свойства, в соответствии с инструкциями класса, используя это ключевое слово this. Подумайте об этом, как о коробке, едущей по конвейеру и наполняемой различными объектами по мере её продвижения. Каждый ее шаг означает: "данная коробка получает такое-то свойство", "данная коробка получает такое-то свойство"... В нашем примере контейнеру присваивается два свойства: x и y со значениями 5 и 7, соответственно. После достижения конца определения класса, контейнер, которому теперь присвоено два новых свойства, возвращается обратно. Таким образом в строке #6 содержится:
inst1 = << контейнер (объект) с двумя свойствами, x:5 и y:7 >>
Следующее, что нужно сделать - дать контейнеру имя. В нашем примере это "inst1". Вот и всё. Представьте людей, ожидающих коробки в конце конвейера, чтобы написать на них свои имена и затем забрать домой. Теперь это ИХ коробки, тогда как раньше это были ПРОСТО коробки на конвейере. Вот для чего нужна левая часть уравнения в сроке #6 - дать имя объекту. Это происходит, когда класс закончил свою работу. Теперь можете проверить конечный объект на наличие свойств x и y. Они должны иметь значения 5 и 7.
Единственное, что способно определить класс в ActionScript, это функция (по крайней мере в 5-й версии). Это может быть ваша собственная функция или встроенная, такая как Color или Array. Только классы, встроенные или созданные, могут создавать экземпляры. Вскоре мы разделим функции на два типа: классы (classes) и методы (methods). Тогда во избежание путаницы можно будет перестать пользоваться словом "функция".
Скорее всего вы уже знакомы со словом "экземпляр" (instance) по работе с Macromedia Flash. Вы создаёте экземпляры символов, просто "перетаскивая" их из библиотеки на сцену. Это то же самое, что и создание экземпляра из класса, абсолютно то же самое. "Вытаскивая" символ на сцену, вы тем самым создаёте "новый" объект. Таким образом создаётся пустой контейнер (если это мувиклип, то пустой мувиклип). Потом этот контейнер передается шаблону класса и "проходит через него", получая по дороге различные свойства (как на конвейере). Разумеется, класс это описание символа, которое вы находите в библиотеке, а свойства - графические элементы в символе (то, что кладется в коробку на конвейере). Должно быть, вы уже поняли, почему очень удобно пользоваться шаблонами (template) для создания объектов во Flash'е. По тем же самым причинам удобно пользоваться шаблонами и в ActionScript.
Возможно, вам кажется, что не всякий класс получает "безымянный" контейнер. Это отчасти верно, например:
A = function() { return 7; } y = A(); // 7
Первое, что следует отметить, это не класс. Классы никогда не возвращают значений и они всегда вызываются с помощью оператора new. На самом же деле это метод (method), о котором речь пойдёт несколько позже. А пока вкратце скажем, что метод это функция (function), имеющая принадлежность к классу. Фактически термины "функция" и "метод" часто взаимозаменяемы. "Классы" же, это совсем другое дело. Как бы мы ни называли их, все функции "принимают" объекты и присваивают им значение this. Классы "принимают" пустые объекты, а методы принимают существующие объекты. Но вернёмся к нашим примерам...
Написав A(), может показаться, что мы никоим образом не отправляем объект в функцию, чтобы "налепить" на него свойства. Откуда бы ему взяться? Однако, если даже вы не определяете объект (как в случае с использованием new, или inst.A();), то в этом случае под объектом подразумевается (и соответственно направляется) текущий контейнер. Контейнер, в котором помещается весь этот код это, конечно же, _root (то есть _level0, если именно отсюда берётся код). Таким образом, используется именно этот контейнер. ( A() на самом деле означает _root.A(); ). Следующий код показывает это:
A = function() { this.x = 5; // _root.x = 5 return 7; } var y = A(); trace (_root.x); // 5 trace (y); // 7
Как мы видим, _root был отослан в функцию и присвоен ключевому слову this. После выполнения функции, свойства, назначенные параметру this, также стали распространяться и на _root, как следует из вышеприведённого примера.
<<
ООП во Flash 5 >>