Руководство по actionscript. часть 2, стр. 117

Синтаксические правила, применяемые к идентификаторам, не распространяются на переменные, которые создаются с использованием оператора [ ]. Например, следующий код создает динамическую переменную экземпляра, имя которой начинается с цифры:

var info:Object = new Object( ); info["411"] = «Information Line»;

Использование оператора «точка» (.) для создания той же переменной вызовет ошибку, поскольку такая запись нарушает синтаксические правила, применяемые к идентификаторам:

var info.-Object = new Object ( );

info.411 = «Information Line»; // ОШИБКА! Идентификаторы не должны

// начинаться с цифры

Стоит отметить, что описанная методика может использоваться для обращения не только к динамическим переменным экземпляра, но и к любым типам переменных и методов. Однако наиболее часто она применяется при работе именно с динамическими переменными экземпляра. Следующий раздел демонстрирует использование динамических обращений в практической ситуации: для создания справочной таблицы.

Использование динамических переменных экземпляра для создания справочных таблиц

Справочная таблица — это структура данных, которая связывает набор имен с соответствующим набором значений. Например, следующий псевдокод демонстрирует справочную таблицу, которая представляет меню (приводится по-русски):

закуска: маисовые чипсы

основное блюдо: лепешка с начинкой из бобов

десерт: пирожное

Чтобы представить данную справочную таблицу с помощью динамических переменных экземпляра, можно использовать следующий код:

var meal:0bject = new Object( ); meal. appetizer = «tortilla chips»; meal. maincourse = «bean burrito»; meal. dessert = «cake»;

Теперь рассмотрим более сложный сценарий. Представьте приложение для инвентаризации книг в книжном магазине, которое позволяет пользователю искать книги по номеру ISBN. Информация о каждой книге загружается с внешнего сервера. Чтобы минимизировать количество обращений к серверу, приложение загружает за раз информацию о 500 книгах. Для упрощения будем полагать, что информация о каждой книге представлена в виде отдельной строки, имеющей следующий формат:

«Price: $19.99. Title: Path of the Paddle»

Для хранения загруженной информации о книге в программе на языке ActionScript создадим экземпляр класса Ob j ect, который будет служить справочной таблицей для книг:

var bookList:Object = new 0bject( ):

Загруженную информацию о каждой книге мы присваиваем новой динамической переменной экземпляра созданного объекта bookList. Имя каждой переменной соответствует ISBN-номеру книги с предшествующей строкой «isbn». Например, переменная для книги с ISBN-номером 155209328Х будет называться isbnl5520 932 8X. Следующий код демонстрирует создание динамической переменной экземпляра для данной книги в том случае, если бы мы заранее знали ее ISBN-номер:

bookList. isbnl55209328X = «Price: $19.95. Title: Path of the Paddle»;

В реальном приложении тем не менее ISBN-номер книги станет известен только после того, как информация об этой книге будет загружена с сервера. Следовательно, имя динамической переменной экземпляра для каждой книги должно формироваться динамически, на основании загружаемых данных. Для демонстрационных целей создадим переменную bookDatа, значение которой будет представлять данные в том виде, в котором они были бы загружены с сервера. В этом упрощенном примере ISBN-номер и подробная информация о каждой книге разделяются одиночным символом «тильда» (-). При этом полная информация о каждой книге отделяется двойным символом «тильда»

var bookData:String = «155209328X~Price: $19.95. Title: Path of the Paddle» + «—»

+ «0072231726-Price: $24.95. Title: High Score!»;

Чтобы преобразовать загруженные данные о книгах из строки в массив книг для обработки, воспользуемся методом split ( ) класса String, как показано в следующем коде:

var bookDataArray. Array = bookData. split(«—»):

Для преобразования массива книг в справочную таблицу используем следующий код:

// Создаем переменную, которая будет хранить информацию о каждой книге // в процессе обработки var book:Array;

// Выполнить цикл один раз для каждого элемента в массиве книг for (var i:int = 0; i < bookdataarray.length; i++) {

// Преобразуем текущий элемент массива из строки в собственный массив. // Например, строка:

// «155209328X~Price: $19.95. Title: Path of the Paddle» // становится массивом:

// ["155209328X", "Price: $19.95. Title: Path of the Paddle"] book = bookDataArray[i].split(«~»);

// Создаем динамическую переменную экземпляра, имя которой соответствует

// ISBN-номеру текущего элемента в массиве книг, и присваиваем этой

// переменной описание текущего элемента в массиве. Обратите внимание, что

// ISBN-номер представлен выражением book[0], а описание -

// выражением Ьоок[1].

Руководство по actionscript. часть 2, стр. 118

Bookl_ist["isbn" + book[0]] = book[l];

}

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

trace(bookList["isbn" + isbnlnput. text]);

Следующим же образом мы бы выводили информацию о выбранной пользователем книге на экране в текстовом поле, на которое ссылается переменная

bookDescription:

bookDescription. text = bookl_ist["isbn" + isbnlnput. text];

Для отображения списка всех книг, хранящихся в объекте bookList, можно использовать цикл for-each-in, как показано в следующем коде:

for each (var booklnfo:* in bookList) { // Выводим значение динамической переменной экземпляра, // обрабатываемой в текущий момент trace(booklnfo);

}

В результате выполнения цикла будет выведена следующая отладочная информация:

Price: $19.95. Title: Path of the Paddle Price: $24.95. Title: High Score!

Создание справочных таблиц с помощью литералов объекта. Для удобства справочные таблицы, содержимое которых имеет фиксированный размер и известно заранее, можно создавать с помощью литерала объекта. Литерал объекта создает новый экземпляр класса Ob j ect из набора пар «имя/значение», которые представляют динамические переменные экземпляра, разделены запятыми и заключены в фигурные скобки. Вот общий синтаксис:

{имяПеременной1:значениеПеременной!, имяПеременной2:значениеПеременной2,

имяПеременнойМ:значениеПеременнойИ}

Например, следующий код создает экземпляр класса Ob j ect с динамической переменной экземпляра city (значением которой является «Toronto») и динамической переменной экземпляра country (значением является «Canada»):

var info:Object = {city:»Toronto», country:»Canada»};

Данный код идентичен следующему:

var info:Object = new Object( ); info. city = «Toronto»; info. country = «Canada»;

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

var bookList:Object = {

isbnl55209328X:»Price: $19.95. Title: Path of the Paddle».

Руководство по actionscript. часть 2, стр. 119

Isbn0072231726:»Price: $24.95. Title: High Score!»

}:

Использование функций для создания объектов

В процессе чтения этой книги вы видели, что большинство объектов в языке ActionScript создается с помощью классов. Тем не менее существует возможность создавать объекты с использованием независимых замыканий функций. Следующий код демонстрирует общий подход. В нем для примера объявлена функция Employee ( ), которая применяется для создания объекта:

// Создаем функцию function Employee ( ) { }

// Используем функцию для создания объекта и присваиваем этот объект

// переменной worker

var worker = new Employee( );

Обратите внимание, что переменная worker является нетипизированной. С точки зрения типов данных объект, на который ссылается переменная worker, представляет собой экземпляр класса Object. Класс Employee не существует, поэтому не существует и тип данных Employee. Таким образом, следующий код вызовет ошибку (поскольку тип данных Employee не существует):

// ОШИБКА!

var worker-.Employee = new Employee( );

Замыкание функции, используемое для создания объекта, называется функцией-конструктором (не путайте с л*еяюдо. м-конструктором, который является частью определения класса). В языке ActionScript 3.0 независимые функции, объявленные на уровне пакета, не могут применяться в качестве функций-конструкторов, ио: этому предыдущий код должен быть размещен внутри метода, в коде за пределами описания пакета или в сценарии кадра на временной шкале в среде разработки Flash. Тем не менее ради краткости в этом разделе все функции-конструкторы

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

Руководство по actionscript. часть 2, стр. 120

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

function Employee (age, salary) { // Описываем динамические переменные экземпляра this. age = age: this. salary = salary;

}

// Передаем аргументы, которые будут использованы в качестве значений // динамических переменных экземпляра данного объекта var worker = new Employee(25, 27000); trace(worker. age); // Выводит: 25

Чтобы объекты, создаваемые с помощью определенной функции-конструктора, могли разделять между собой информацию и поведение, язык ActionScript для каждой функции вводит специальную статическую переменную prototype. Переменная функции prototype ссылается на объект (называемый объектом-прототипом функции), к динамическим переменным экземпляра которого можно обращаться через любой объект, созданный с помощью данной функции. Изначально язык ActionScript присваивает переменной prototype каждой функции экземпляр базового класса Object. Добавляя в этот объект динамические переменные экземпляра, мы можем создать информацию и поведение, разделяемые между всеми объектами, созданными из конкретной функции.

Например, следующий код добавляет динамическую переменную экземпляра company в объект prototype функции Employee ( ):

Employee. prototype. company = «AnyCorp»;

В результате любой объект, созданный из функции Employee ( ), может обращаться к переменной company так, будто это его собственная динамическая переменная экземпляра:

var worker = new Employee(25, 27000); trace(worker. company); // Выводит: AnyCorp

В предыдущем коде, когда среда выполнения Flash поймет, что объект, созданный из функции Employee ( ) (worker), не имеет переменной экземпляра или метода экземпляра с именем «company», она проверит, определена ли динамическая переменная экземпляра с таким именем в объекте Employee. prototype. В этом объекте такая переменная определена’ поэтому среда Flash использует ее так, будто это собственная переменная объекта worker.

Если, с другой стороны, в объекте worker определена собственная переменная company, она будет использована вместо переменной объекта Employee. prototype. Это демонстрирует следующий код:

var worker = new Employee(25, 27000); worker. company = «CarCompany»;

trace(worker. company); // Выводит: CarCompany (не AnyCorp)

Используя методику, рассмотренную в разд. «Динамическое добавление нового поведения в экземпляр», мы можем присвоить функцию динамической переменной экземпляра объекта prototype любой функции-конструктора. Эта функция в дальнейшем может быть использована любым объектом, созданным из данной функции-конструктора.

Руководство по actionscript. часть 2, стр. 121

Например, следующий код определяет динамическую переменную экземпляра getBonus в объекте prototype функции Employee ( ) и присваивает этой переменной функцию, которая подсчитывает и возвращает премию по итогам года:

Employee. prototype. getBonus = function (percentage:int).-Number { // Возвращает размер премии в зависимости от зарплаты сотрудника // и указанного процента return this. salary * (percentage/100);

}

В результате все объекты, созданные из функции Employee ( ), могут использовать функцию getBonus ( ) так, будто она была присвоена их собственным динамическим переменным экземпляра:

var worker = new Employee(25, 27000); trace(worker. getBonusdO)); // Выводит: 2700

Использование объектов-прототипов для дополнения классов

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

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

Например, следующий код определяет новую динамическую переменную экземпляра isEmpty в объекте prototype внутреннего класса String и присваивает ей функцию. Эта функция возвращает значение true, когда строка не содержит символов; в противном случае функция возвращает значение false:

String. prototype. isEmpty = function ( ) { return (this == «») ? true : false;

}:

Для вызова функции isEmpty ( ) над объектом String мы используем следующий код:

var si:Stri ng = «Hello World»; var s2:String = «»;

trace(sl. isEmpty( )); // Выводит: false trace(s2.isEmpty( )); // Выводит: true

Тем не менее в предыдущем примере кода — и вообще во всей этой методике — существует проблема: динамическая переменная экземпляра добавляется только на этапе выполнения программы; следовательно, компилятор не имеет ни малейшего представления о том, что эта переменная существует, и сгенерирует ошибку, если компиляция программы будет выполняться в строгом режиме. Например, при компиляции программы в строгом режиме код из предыдущего примера вызовет следующую ошибку:

Call to a possibly undefined method isEmpty through a reference with static type String.

Руководство по actionscript. часть 2, стр. 122

Яо-русски она будет звучать так: Вызов возможно неопределенного метода isEmpty через ссылку на статический тип String.

Чтобы обращение к функции isEmpty ( ) при использовании строгого режима не приводило к ошибке на этапе компиляции, мы должны применять динамическое обращение, как показано в следующем коде:

sl["isEmpty"]( )

С другой стороны, если бы класс String не был объявлен с использованием атрибута dynamic, первоначальный подход (то есть si. isEmpty ( ) ) не вызывал бы ошибку.

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

Цепочка прототипов

Из предыдущих разделов мы узнали, что объект-прототип может использоваться для разделения информации и поведения между объектами, созданными т определенной <^нкнда-констр^ктора или класса. фактически обращаться к данному объекту-прототипу можно и за пределами объектов, созданных из функции или класса, которому принадлежит данный прототип.

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

// Создаем простейший класс А dynamic public class А {

}

// Создаем другой простейший класс В, который расширяет класс А

dynamic public class В extends А {

}

// Создаем основной класс приложения public class Main extends Sprite { public function Main ( ) {

// Добавляем динамическую переменную экземпляра в объект-прототип

// класса А

A. prototype. day = «Monday»;

// Обращаемся к переменной A. prototype. day через экземпляр класса В

var b:B = new В( );

trace(b. day); // Выводит: «Monday»

}

}

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

Руководство по actionscript. часть 2, стр. 123

Рассмотрим, как работают цепочки прототипов. Предположим, что мы создаем функцию Employee ( ), как делали это раньше, в объекте-прототипе которой определяем динамическую переменную экземпляра company:

function Employee ( ) { } •

Employee. prototype. company = «AnyCorp»;

Любой объект, созданный из функции Employee ( ), может обращаться к переменной company через объект-прототип функции Empoyee ( ). Ничего нового. Теперь предположим, что мы создали еще одну функцию Manager ( ):

function Manager ( ) { }

Предположим также, что необходимо сделать так, чтобы объекты, созданные из функции Manager ( ), могли обращаться к переменной company через объект-прототип функции Employee ( ). Для этого мы присваиваем объект, созданный из функции Employee ( ), переменной prototype функции Manager ( ).

Manager. prototype = new Employee( );

Теперь рассмотрим, что произойдет, если мы обратимся к переменной с именем » company» через объект, созданный из функции Manager ( ), как показано в следующем коде:

var worker = new Manager( ); trace(worker. company);

При выполнении предыдущего кода среда Flash проверяет, имеет ли объект worker переменную или метод экземпляра с именем » company». Объект worker не имеет

переменной или метода экземпляра с таким именем, поэтому далее среда выполнения Flash проверяет, определена ли динамическая переменная экземпляра с именем «company» в объекте-прототипе функции Manager ( ). Сам по себе объект-прототип функции Manager ( ) является объектом, созданным из функции Employee ( ). Тем не менее в объектах, созданных из функции Employee ( ), динамическая переменная экземпляра с именем «company» не определена. Следовательно, после этого среда Flash проверяет, определена ли динамическая переменная экземпляра с именем » company» в объекте-прототипе функции Employee ( ). В нем такая переменная определена, поэтому среда выполнения Flash использует ее так, будто это собственная переменная объекта worker.

Рассмотрим путь, который проходит среда Flash при поиске переменной с именем «company».

1. Ищем переменную company в объекте worker. Не найдена.

Руководство по actionscript. часть 2, стр. 124

2. Ищем переменную company в объекте Manager. prototype. Не найдена.

3. Объект Manager. prototype создан из функции Employee ( ), поэтому ищем переменную company в объекте Employee. prototype. Найдена!

Список объектов-прототипов, просматриваемых средой выполнения Flash при попытке определить значение переменной, называется цепочкой прототипов. До появления языка ActionScript 3.0 цепочка прототипов была основным механизмом для разделения повторно используемого поведения между различными типами объектов. В языке ActionScript 3.0 эту роль играет наследование классов.

Обратите внимание на следующие ограничения, налагаемые на цепочки прототипов в ActionScript 3.0.

? Объект, присваиваемый переменной prototype функции, сам по себе должен являться объектом, созданным из функции, или экземпляром класса Object (использование экземпляров других классов не допускается).

? Значение переменной prototype класса присваивается средой выполнения Flash автоматически и в дальнейшем не может быть изменено.

Вперед!

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

ГЛАВА 18

Область видимости

Область видимости — это физическая область программы, в которой выполняется код. В языке ActionScript существует пять возможных областей видимости:

? тело функции;

? тело метода экземпляра;

? тело статического метода;

? тело класса;

? все остальное (то есть глобальная область видимости).

Руководство по actionscript. часть 2, стр. 125

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

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

public class SomeClass { public function someMethod ( ):void { function someNestedFunction ( ):void { // Область видимости данной функции вложена внутрь области видимости // метода someMethod( ). которая вложена в область видимости класса // SomeClass

}

}

}

Если одна обдасть видимости вложена в другую область, определения (то есть переменные, функции, классы, интерфейсы и пространства имен), доступные во внешней области видимости, становятся доступными во вложенной области. Например, функция, вложенная внутрь метода экземпляра, может обращаться к локальным переменным этого метода. Полный список вложенных областей видимости, окружающих код, выполняемый в текущий момент, называется цепочкой областей видимости.

В этой главе рассматривается доступность переменных, функций, классов, интерфейсов и пространств имен внутри различных областей видимости языка ActionScript.

Обратите внимание, что помимо «доступных» определений, перечисленных в каждом из последующих разделов, определения, объявленные во внешнем пакете с использованием модификатора управления доступом public, можно сделать видимыми и в данной области видимости с помощью директивы import. Подробную информацию можно найти в подразд. «Пример создания объекта: добавление животного в зоопарк» разд. «Создание объектов» гл. 1.

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

Таблица 16.1. Доступность определения в зависимости от его местоположения и используемого модификатора управления доступом

Определение Доступно

Определение за пределами всех пакетов Только внутри исходного файла, содержащего данное определение

Определение в безымянном пакете В любой точке программы

Определение с использованием модификатора управления доступом public в именованном пакете Внутри пакета, содержащего данное определение, и в любом месте, где оно импортируется

Определение с использованием модификатора управления доступом internal в именованном пакете Только внутри пакета, содержащего данное определение

Метод или переменная, объявленные с использованием модификатора управления доступом public В любом месте, где доступен класс, содержащий данное определение

Метод или переменная, объявленные с использованием модификатора управления доступом internal Внутри пакета, содержащего класс с данным определением

Метод или переменная, объявленные с использованием модификатора управления доступом protected Внутри класса, содержащего данное определение, и его классов-потомков

Метод или переменная, объявленные с использованием модификатора управления доступом private Только внутри класса, содержащего данное определение

Определение в методе экземпляра, статическом методе или функции Доступно внутри метода или функции, содержащих данное определение, а также во всех вложенных в них функциях

Глобальная область видимости

Код, помещенный непосредственно в тело пакета или на верхний уровень тела пакета, находится в глобальной области видимости. Иначе говоря:

package {

// Этот код находится в глобальной области видимости

}

// Этот код также находится в глобальной области видимости

Код, находящийся в глобальной области видимости, может обращаться к функциям, переменным, классам, интерфейсам и пространствам имен, определенным:

? на верхнем уровне безымянного пакета;

? за пределами всех пакетов, но в том же исходном файле (AS).

Руководство по actionscript. часть 2, стр. 126

Другими словами:

package {

// Размещенные здесь определения доступны всему коду // в глобальной области видимости

}

// Размещенные здесь определения доступны всему коду в том же исходном файле

Стоит отметить, что код, размещенный на верхнем уровне тела именованного пакета, может также обращаться к определениям, размещенным на верхнем уровне того же пакета. Эти определения доступны потому, что внутри именованного пакета язык ActionScript автоматически открывает пространство имен, связанное с данным пакетом (более подробную информацию можно найти в гл. 17). Иными словами:

package somePackage { // Размещенные здесь определения становятся автоматически доступны // всему коду в пакете somePackage

}

Область видимости класса

Код, помещенный на верхний уровень тела класса, находится в области видимости этого класса. Например:

package { public class SomeClass { // Размещенный здесь код находится в области видимости класса someClass

}

}

Помните, что код, размещенный на верхнем уровне тела класса, включается в автоматически создаваемый статический метод (инициализатор класса), который выполняется всякий раз, когда среда Flash определяет класс на этапе выполнения программы. Подробную информацию можно найти в разд. «Статические методы» гл. 4.



Полезные ссылки
Случайные записи
  • 02.06.2012">Google намерена зарегистрировать домены .google, .docs, .youtube и .lol
  • 03.03.2011">Руководство по actionscript. часть 5, стр. 058
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.110
  • 15.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.48
  • 01.03.2011">Руководство по actionscript. часть 5, стр. 133
  • 20.03.2011">Руководство по actionscript. часть 2, стр. 062
  • 19.03.2011">Руководство по actionscript. часть 2, стр. 098
  • 02.03.2011">Руководство по actionscript. часть 5, стр. 080
  • 19.03.2011">Руководство по actionscript. часть 2, стр. 091
  • 15.03.2011">Руководство по actionscript. часть 3, стр. 039
  • 10.03.2011">Руководство по actionscript. часть 4, стр. 024
  • 17.03.2011">Руководство по actionscript. часть 2, стр. 146
  • 04.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.29
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.100
  • 22.01.2011">Руководство по actionscript. часть 1, стр. 113
Опрос

Какие цвета вы предпочитаете?

View Results

Loading ... Loading ...