close

Вход

Забыли?

вход по аккаунту

?

flash as3 programming

код для вставкиСкачать
Программирование на
ADOBE
®
ACTIONSCRIPT
®
3.0 Авторские права
© Adobe Systems Incorporated, 2008. Все права защищены.
Программирование на Adobe
®
ActionScript
®
3.0 в Adobe
®
Flash
®
Если данное руководство распространяется с программным обеспечением, которое включает соглашение конечного пользователя, то руководство, так же как и описанное в нем программное обеспечение, поставляется по лицензии и может быть использовано или скопировано только в соответствии с условиями этой лицензии. Воспроизведение, хранение в информационно-поисковой системе или передача любых разделов данного руководства в любой форме и любым способом (механическим, электронным, путем записи и т.д.) запрещены без предварительного письменного разрешения Adobe Systems Incorporated. Содержимое данного руководства защищено законом об авторском праве, даже если руководство не распространяется с программным обеспечением, включающим лицензионное соглашение с конечным пользователем.
Содержимое данного руководства предназначено только для информационных целей, может меняться без уведомления и не должно толковаться как обязательство Adobe Systems Incorporated. Adobe Systems Incorporated не несет материальной и прочей ответственности за возможные ошибки и неточности в информационном содержимом этого руководства.
Помните, что существующие изображения и иллюстрации, которые вы можете пожелать включить в проект, могут быть защищены авторскими правами. Незаконное использование таких материалов в новом документе может считаться нарушением прав владельца авторских прав. Получите все необходимые разрешения от владельца авторских прав.
Все названия компаний в образцах шаблонов предназначены только для демонстрационных целей и не могут служить ссылкой на существующую организацию.
Adobe, the Adobe logo, Adobe AIR, ActionScript, Flash, Flash Lite, Flex, Flex Builder, MXML, and Pixel Bender are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries.
ActiveX and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and other countries. Macintosh is a trademark of Apple Inc., registered in the United States and other countries. Java is a trademark or registered trademark of Sun Microsystems, Inc. in the United States and other countries. All other trademarks are the property of their respective owners. This product includes software developed by the Apache Software Foundation (
h
t
t
p://w
w
w
.a
p
ac
h
e
.o
r
g/).
MPEG Layer-3 audio compression technology licensed by Fraunhofer IIS and Thomson Multimedia (
h
t
t
p://w
w
w
.m
p3licen
sin
g
.co
m)
Speech compression and decompression technology licensed from Nellymoser, Inc. (
w
w
w
.n
e
l
l
y
m
os
er
.co
m).
Video compression and decompression is powered by On2 TrueMotion video technology. © 1992-2005 On2 Technologies, Inc. All Rights Reserved. h
t
t
p://w
w
w
.o
n2.co
m.
This product includes software developed by the OpenSymphony Group (
h
t
t
p://w
w
w
.o
p
en
sy
m
p
h
o
n
y
.co
m/).
This product contains either BSAFE and/or TIPEM software by RSA Security, Inc.
Sorenson Spark
™
video compression and decompression technology licensed from Sorenson Media, Inc.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA
Notice to U.S. government end users. The software and documentation are “Commercial Items,” as that term is defined at 48 C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial items and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S. Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250 ,and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be incorporated by reference.
iii
Содержание
Глава 1. О руководстве
Использование руководства . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Как найти документацию по ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Ресурсы по изучению ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Глава 2. Введение в ActionScript 3.0
О языке ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Преимущества ActionScript 3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Новые возможности ActionScript 3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Совместимость с предыдущими версиями . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Глава 3. Начало работы с языком ActionScript
Основы программирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Работа с объектами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Общие элементы программы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Пример: фрагмент анимации портфолио . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Создание приложений с ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Создание пользовательских классов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Пример: создание базового приложения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Рассмотрение последующих примеров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Глава 4. Язык ActionScript и его синтаксис
Обзор языка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Объекты и классы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Пакеты и пространства имен . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Переменные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Типы данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Синтаксис . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Операторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Условия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Повтор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Глава 5. Объектно-ориентированное программирование на языке ActionScript
Основы объектно-ориентированного программирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Классы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Интерфейсы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Наследование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Дополнительные темы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Пример: GeometricShapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Глава 6. Работа с датами и временем
Основы работы с датами и временем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Управление календарными датами и временем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
iv
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Содержание
Управление временными интервалами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Пример: простые аналоговые часы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Глава 7. Работа со строками Основные сведения о строках . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Создание строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Свойство length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Работа с символами в строках . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Сравнение строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Получение строковых представлений других объектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Сцепление строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Поиск подстрок и шаблонов в строках . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Перевод строк в верхний или нижний регистр . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Пример: ASCII-графика . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Глава 8. Работа с массивами
Основные сведения о массивах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Индексные массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Ассоциативные массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Многомерные массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Клонирование массивов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
Дополнительные темы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Пример: PlayList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Глава 9. Обработка ошибок
Основы обработки ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Типы ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Обработка ошибок в ActionScript 3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Работа с версиями Flash Player и AIR, имеющими встроенные программы отладки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Обработка синхронных ошибок в приложении . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Создание пользовательских классов ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Ответы на события ошибок и ошибки состояния . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Сравнение классов ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Пример: приложение CustomErrors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Глава 10. Использование регулярных выражений
Основы регулярных выражений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Синтаксис регулярных выражений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Методы для использования регулярных выражений со строками . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
Пример: синтаксический анализатор Wiki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
Глава 11. Работа с XML
Основы XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
Подход E4X к обработке XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Объекты XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Объекты XMLList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Инициализация переменных XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
Компоновка и преобразование объектов XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
v
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Содержание
Пересечение XML-структур . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
Использование пространств имен XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
Преобразование типа XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Чтение внешних XML-документов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
Пример: загрузка RSS-данных из Интернета . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Глава 12. Обработка событий
Основы обработки событий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
Чем обработка событий в ActionScript 3.0 отличается от предыдущих версий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
Поток событий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Объекты Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Прослушиватели событий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Пример: будильник . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Глава 13. Программирование отображаемого содержимого
Основы программирования отображаемого содержимого . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Основные классы показа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Преимущества подхода с использованием списка отображения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
Работа с экранными объектами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Операции с экранными объектами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
Анимация объектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
Динамическая загрузка содержимого для показа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
Пример: SpriteArranger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
Глава 14. Использование прикладного программного интерфейса (API) рисования
Основы использования прикладного программного интерфейса (API) рисования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Понимание класса Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
Создание линий и кривых . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
Создание фигур с помощью встроенных методов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Создание линий и заливок градиента . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
Использование класса Math с методами рисования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
Анимирование с помощью прикладного программного интерфейса (API) рисования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Пример: наглядный алгоритмический генератор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Использование прикладного программного интерфейса (API) рисования для опытных пользователей . . . . . . . . . . . 355
Создание контуров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Определение правил поворотов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Использование классов графических данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
Об использовании drawTriangles() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Глава 15. Работа с геометрией
Основы геометрии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
Использование объектов Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
Использование объектов Rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
Использование объектов Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
Пример: применение матричного преобразования к экранному объекту . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
vi
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Содержание
Глава 16. Фильтрация экранных объектов
Основы фильтрации экранных объектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
Создание и применение фильтров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Доступные фильтры показа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
Пример: Filter Workbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
Глава 17. Работа с шейдерами Pixel Bender
Основные сведения о шейдерах Pixel Bender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
Загрузка или встраивание шейдера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
Получение метаданных шейдера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
Указание значений вводов и параметров шейдера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
Использование шейдера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
Глава 18. Работа с фрагментами роликов
Основные сведения о фрагментах роликов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432
Работа с объектами MovieClip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
Управление воспроизведение фрагмента ролика . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
Создание объектов MovieClip с помощью ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
Загрузка внешнего SWF-файла . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
Пример: RuntimeAssetsExplorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Глава 19. Работа с анимацией движения
Основные сведения об анимации движения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
Копирование сценариев анимации движения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
Встраивание сценариев анимации движения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
Описание анимации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
Добавление фильтров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
Связывание анимации движения с ее экранными объектами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
Глава 20. Работа с обратной кинематикой
Основы обратной кинематики . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
Обзор анимации каркасов ОК . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
Получение сведений о каркасе ОК . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
Создание экземпляра IK Mover и ограничение его движения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
Перемещение каркаса ОК . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
Использование событий ОК . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
Глава 21. Работа с текстом
Основы работы с текстом . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Использование класса TextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
Использование Flash Text Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
Глава 22. Работа с растровыми изображениями Основы работы с растровыми изображениями . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
Классы Bitmap и BitmapData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
Управление пикселами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
Копирование данных растровых изображений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
Создание текстур с помощью функций шумов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518
vii
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Содержание
Прокрутка изображений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520
Выполнение множественного отображения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
Пример: анимация вращающейся луны . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
Глава 23. Работа в трех измерениях (3D)
Основы работы в трех измерениях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
Сведения о трехмерных функциях проигрывателя Flash Player и среды выполнения AIR . . . . . . . . . . . . . . . . . . . . . . . . . . 534
Создание и перемещение трехмерных объектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
Проецирование трехмерных объектов на двухмерный вид . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538
Пример: перспективная проекция . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
Выполнение сложных трехмерных преобразований . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
Использование треугольников для создания трехмерных эффектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
Глава 24. Работа с видео
Основы видео . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553
Сведения о видеоформатах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555
Понимание класса Video . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
Загрузка видеофайлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
Управление воспроизведением видео . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
Воспроизведение видео в полноэкранном режиме . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
Потоковые видеофайлы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
Понимание ключевых точек . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
Написание методов обратного вызова для метаданных и ключевых точек . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566
Использование ключевых точек и метаданных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
Захват данных камеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
Отправление видеоданных на сервер . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
Дополнительные темы о FLV-файлах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587
Пример: Video Jukebox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
Глава 25. Работа со звуком
Основные сведения о работе со звуком . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595
Обзор архитектуры звука . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
Загрузка внешних звуковых файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598
Работа с встроенными звуками . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
Работа с потоковыми аудиофайлами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
Работа с динамически создаваемым звуком . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
Воспроизведение звуков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604
Безопасность при загрузке и воспроизведении звуков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608
Управление громкостью и панорамированием звука . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
Работа с метаданными звука . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 610
Получение необработанных аудиоданных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
Захват вводимого звука . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
Пример: проигрыватель подкастов PodcastPlayer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618
Глава 26. Захват действий пользователя
Основные сведения о действиях пользователя . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626
Захват действий клавиатуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
viii
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Содержание
Захват действий мыши . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
Пример: WordSearch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
Глава 27. Сетевые подключения и связь
Основные сведения о сетевых подключениях и связи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638
Работа с внешними данными . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641
Подключение к другим экземплярам Flash Player и AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
Подключения к сокетам . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
Хранение локальных данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
Работа с файлами данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658
Пример: создание клиента Telnet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
Пример: отправка и загрузка файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675
Глава 28. Среда клиентской системы
Основные сведения о среде клиентской системы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 681
Использование класса System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683
Использование класса Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 684
Использование класса ApplicationDomain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685
Использование класса IME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687
Пример: определение возможностей системы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 692
Глава 29. Копирование и вставка
Основы копирования и вставки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697
Чтение и запись системного буфера обмена . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 698
Форматы данных буфера обмена . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 698
Глава 30. Печать Основные сведения о печати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703
Печать страницы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704
Задачи проигрывателя Flash Player или AIR и системная печать . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705
Настройка размера, масштаба и ориентации страницы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 708
Пример: многостраничное задание печати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 710
Пример: масштабирование, обрезка и динамическая настройка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712
Глава 31. Использование внешнего API
Основы использования внешнего API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
Требования к внешнему API и преимущества . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716
Использование класса ExternalInterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717
Пример: использование внешнего API с контейнером веб-страницы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 721
Пример: использование внешнего API с контейнером ActiveX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 727
Глава 32. Безопасность проигрывателя Flash Player
Общие сведения о безопасности проигрывателя Flash Player . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733
Изолированные программные среды . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735
Элементы управления разрешениями . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 738
Ограничение API-интерфейсов сетевого подключения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745
Безопасность в полноэкранном режиме . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 748
Загрузка содержимого . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749
ix
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Содержание
Перекрестное выполнение сценариев . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 752
Получение данных загруженного мультимедийного содержимого . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755
Загрузка данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758
Загрузка встроенного содержимого из SWF-файлов, импортированных в домен безопасности . . . . . . . . . . . . . . . . . . . 760
Работа с устаревшим содержимым . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761
Установка прав доступа LocalConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761
Управление доступом к внешним URL-адресам . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762
Общие объекты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 764
Доступ к камере, микрофону, буферу обмена и клавиатуре . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765
Указатель ..........................................................................................................766
1
Глава 1. О руководстве
В руководстве освещаются основы разработки приложений на языке Adobe® ActionScript® 3.0. Для наилучшего понимания описываемых принципов и техник вы должны быть знакомы с основными понятиями программирования, такими как типы данных, переменные, циклы и функции. Вы должны понимать основные принципы объектно-ориентированного программирования, такие как классы и наследование. Знание языка ActionScript версии 1.0 или 2.0 будет полезно, но необязательно.
Использование руководства
Главы руководства разбиты на логические группы, чтобы вам было удобнее находить связанные темы в документации по ActionScript. Также в руководстве содержатся многочисленные примеры файлов, демонстрирующих принципы программирования с участием важных или часто используемых классов. Образцы файлов объединены в пакеты таким образом, чтобы их было легче загружать и использовать с Adobe® Flash® CS4 Professional. Они также могут включать файлы-оболочки. Тем не менее, ключевым образцом является сам код ActionScript 3.0, который можно использовать в любой среде разработки.
Язык ActionScript 3.0 можно использовать для написания и компиляции программ несколькими способами, среди которых:
•
использование среды разработки Adobe Flex Builder 3;
•
использование любого текстового редактора и компилятора командной строки, например компилятора Flex Builder 3;
•
использование средства разработки Adobe® Flash® CS4 Professional.
Дополнительную информацию о средах разработки ActionScript см. в разделе «Введение в ActionScript 3.0» на странице 4
Примеры кода в данном руководстве будут понятны и тем читателям, у которых нет опыта работы с интегрированными средами разработки ActionScript (например, Flex Builder или средство разработки Flash). Тем не менее, придется обращаться к документации по этим средствам за информацией о том, как писать и компилировать код ActionScript 3.0. Дополнительную информацию см. в разделе «Как найти документацию по ActionScript» на странице 2.
Главы Описание
Главы с 2 по 5: краткий обзор программирования на ActionScript
В них обсуждаются основные понятия, связанные с ActionScript 3.0, включая синтаксис языка, инструкции, операторы, а также объектно-ориентированное программирование на языке ActionScript.
Главы с 6 по 11: основные типы данных и классы ActionScript 3.0
В них описываются типы данных верхнего уровня в ActionScript 3.0.
Главы с 12 по 32: API-интерфейсы проигрывателя Flash и среды Adobe AIR
В них рассматриваются важные функции пакетов и классов, используемых проигрывателем Adobe Flash Player и средой Adobe AIR, включая обработку событий, работу с экранными объектами и списком отображения, работу и коммуникации в сети, ввод и вывод файлов, внешний интерфейс, модель безопасности приложения и многое другое.
2
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
О руководстве
Как найти документацию по ActionScript
Так как целью данного руководства является описание ActionScript 3.0 — объектно-ориентированного языка с богатыми возможностями, в нем недостаточно подробно освещается процесс разработки приложений с помощью тех или иных средств или серверных архитектур. Поэтому в дополнение к руководству Программирование на ActionScript 3.0 рекомендуем в процессе проектирования, разработки, тестирования и развертывания приложений ActionScript 3.0 обращаться к другим справочникам.
Документация по ActionScript 3.0
Данное руководство призвано познакомить вас с принципами языка программирования ActionScript 3.0, а также с подробностями реализации и примерами, иллюстрирующими важные особенности языка. Тем не менее, данное руководство нельзя считать исчерпывающим источником информации по этому языку. За дополнительной информацией обратитесь к справочнику по языку ActionScript 3.0 и компонентам, в котором описываются все классы, методы, свойства и события языка. В справочнике по языку ActionScript 3.0 и компонентам приводится детальная информация о ключевых компонентах инструмента разработки Flash (в пакетах fl) и API-интерфейсах проигрывателя Flash Player и среды Adobe AIR (в пакетах flash).
Документация по Flash
При использовании инструмента разработки Flash рекомендуется ознакомиться перечисленными ниже руководствами.
Руководство Описание
Использование Flash В нем рассказывается, как разрабатывать динамические веб-приложения в инструменте разработки Flash.
Программирование на ActionScript 3.0 В нем рассказывается об особых случаях использования языка ActionScript 3.0 и основном API-интерфейсе проигрывателя Flash Player и среды Adobe AIR.
Справочник по языку ActionScript 3.0 и компонентам В нем рассказывается о синтаксисе и использовании компонентов инструмента разработки Flash и API-интерфейса ActionScript 3.0 и приводятся примеры кода.
Использование компонентов ActionScript 3.0 В нем детально описывается использование компонентов для разработки приложений, созданных в Flash.
Разработка приложений AIR с помощью Adobe Flash CS4 Professional
В нем рассказывается, как разрабатывать и развертывать приложения Adobe AIR с помощью ActionScript 3.0 и API-интерфейса Adobe AIR во Flash.
Изучение ActionScript 2.0 в Adobe Flash В руководстве описывается синтаксис языка ActionScript 2.0 и рассказывается о том, как использовать ActionScript 2.0 при работе с различными типами объектов.
Справочник по языку ActionScript 2.0 В нем рассказывается о синтаксисе и использовании компонентов инструмента разработки Flash и API-интерфейса ActionScript 2.0 и приводятся примеры кода.
Использование компонентов ActionScript 2.0 В нем рассказывается о том, как использовать компоненты ActionScript 2.0 для разработки приложений, созданных в Flash. Справочник по языку ActionScript 2.0 и компонентам В нем описываются все компоненты Adobe Component Architecture версии 2 и ее API-интерфейсы.
Расширения Flash В нем описываются объекты, методы и свойства API-интерфейса JavaScript.
3
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
О руководстве
Ресурсы по изучению ActionScript
В дополнение к этим руководствам Adobe регулярно публикует статьи, дизайнерские идеи и примеры на страницах Центра разработчиков Adobe и Центра дизайна Adobe.
Центр разработчиков Adobe
Центр разработчиков Adobe — это источник самой свежей информации об ActionScript, статей о практике разработки приложений и ответов на все возникающие вопросы. Посетите Центр разработчиков по адресу: www.adobe.com/devnet/.
Центр дизайна Adobe
Узнайте последние тенденции в области цифрового дизайна, графики и анимации. Вы можете просматривать работы ведущих дизайнеров, знакомиться с последними веяниями в области дизайна, а также совершенствовать свои навыки с помощью самоучителей, алгоритмов работы и дополнительных техник. Дважды в месяц на сайте Центра публикуются свежие самоучители и статьи, а также примеры интересных работ. Посетите Центр дизайна по адресу: www.adobe.com/designcenter/.
Начало работы с Flash Lite 2.x
В нем рассказывается, как использовать Adobe
®
Flash
®
Lite
™
2.x для разработки приложений, описывается синтаксис и использование языка, а также приводятся примеры кода, иллюстрирующие особенности ActionScript, поддерживаемые Flash Lite 2.x
Разработка приложений Flash Lite 2.x В нем объясняются вопросы разработки приложений Flash Lite 2.x
Знакомство с ActionScript для Flash Lite 2.x В нем рассказывается, как разрабатывать приложения с помощью Flash Lite 2.x, и описываются все особенности ActionScript, доступные разработчикам Flash Lite 2.x.
Справочник по языку ActionScript для Flash Lite 2.x В нем приводятся примеры синтаксиса, кода и использования API-
интерфейсов ActionScript 2.0 для Flash Lite 2.x.
Начало работы с Flash Lite 1.x В нем рассматриваются основы Flash Lite 1.x и описывается процесс тестирования содержимого с помощью эмулятора Adobe
®
Device Central CS4.
Разработка приложений Flash Lite 1.x В нем рассказывается, как разрабатывать приложения для мобильных устройств с помощью Flash Lite 1.x.
Изучение ActionScript для Flash Lite 1.x В нем описывается, как использовать ActionScript в приложениях Flash Lite 1.x, а также рассказывается о функциях ActionScript, поддерживаемых Flash Lite 1.x.
Справочник по языку ActionScript для Flash Lite 1.x В нем описывается синтаксис и использование элементов ActionScript в Flash Lite 1.x.
Руководство Описание
4
Глава 2. Введение в ActionScript 3.0
В этой главе представлен обзор Adobe® ActionScript® 3.0, самой современной и эффективной версии языка ActionScript.
О языке ActionScript
ActionScript является языком программирования, используемым в средах выполнения Adobe® Flash® Player и Adobe® AIR™. Он обеспечивает интерактивность, обработку данных и многие другие возможности в содержимом Adobe Flash, Flex и AIR, а также в приложениях. ActionScript выполняется виртуальной машиной ActionScript (AVM), которая является частью проигрывателя Flash Player и пакета AIR. Обычно код ActionScript компилируется в формате байт-кодов (разновидность языка программирования, записываемого и распознаваемого компьютерами) компилятором, таким, какой встроен в Adobe® Flash® CS4 Professional или Adobe® Flex™ Builder™, а также доступен в Adobe® Flex™ SDK. Байт-
коды встраиваются в SWF-файлы, которые выполняются в проигрывателе Flash Player и AIR.
ActionScript 3.0 предлагает надежную модель программирования, знакомую разработчикам, имеющим базовые понятия об объектно-ориентированном программировании. Ниже перечислены некоторые из основных функций ActionScript 3.0, добавленные в процессе усовершенствования предыдущих версий ActionScript. •
Новая виртуальная машина ActionScript, называемая AVM2, использует новый набор инструкций в байт-
кодах и обеспечивает значительный прирост производительности
•
Более современный программный код компилятора выполняет оптимизацию на более высоком уровне, чем предыдущие версии компилятора.
•
Расширенный и улучшенный интерфейс программирования приложений (API) с контролем объектов на нижнем уровне и подлинной объектно-ориентированной моделью
•
Интерфейс программирования приложений XML создан на основе спецификации ECMAScript для XML (E4X) (ECMA-357 редакция 2). E4X является расширением языка ECMAScript, который добавляет XML в качестве поддерживаемого языком типа данных.
•
Модель события на основе спецификации событий DOM уровня 3
Преимущества ActionScript 3.0
ActionScript 3.0 превосходит возможности создания сценариев предыдущих версий ActionScript. Специально разработан, чтобы облегчить создание сложных приложений с большим набором данных и объектно-
ориентированным, многократно используемым программным кодом. Хотя ActionScript 3.0 не обязателен для содержимого, выполняемого в Adobe Flash Player, он открывает возможность повышения производительности, доступные только с AVM2, новой виртуальной машиной. Код ActionScript 3.0 может выполняться до десяти раз быстрее, чем код прежней версии ActionScript.
5
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Введение в ActionScript 3.0
Более старая версия виртуальной машины ActionScript, AVM1, выполняет код ActionScript 1.0 и ActionScript 2.0. AVM1 поддерживается в Flash Player 9 и 10 для обратной совместимости с существующим и старым содержимым. Дополнительные сведения см. в разделе «Совместимость с предыдущими версиями» на странице 8.
Новые возможности ActionScript 3.0
Хотя ActionScript 3.0 содержит много классов и возможностей, знакомых программирующим на ActionScript, архитектурная и концептуальная составляющие ActionScript 3.0 отличаются от предыдущих версий ActionScript. Улучшения в ActionScript 3.0 включают новые возможности языка ядра и усовершенствования в прикладном интерфейсе программирования Flash Player, которые обеспечивают улучшенное управление объектами нижнего уровня.
Примечание. Приложения Adobe® AIR™ также могут использовать прикладные программные интерфейсы Flash Player.
Возможности языка ядра
Язык ядра определяет основные конструктивные элементы языка программирования, такие как инструкции, выражения, условия, циклы и типы. ActionScript 3.0 содержит много новых возможностей, которые ускоряют процесс разработки.
Исключения при выполнении
В ActionScript 3.0 предусмотрены сообщения о большем числе ошибок, чем в предыдущих версиях ActionScript. Исключения при выполнении используются для обработки общих ошибок, они улучшают возможности отладки разрабатываемых приложений, обеспечивая надежную обработку всех возникающих ошибок. Для возникающих при выполнении ошибок можно получить стек-трейсы, снабженные комментариями из исходного файла, а также информацией о номере строки, что позволяет быстро выявить ошибки.
Типы выполнения
В ActionScript 2.0 указания типов переменных служили в первую очередь подсказками разработчикам; при выполнении все значения вводились динамически. В ActionScript 3.0 информация типов сохраняется во время выполнения и используется в нескольких целях. Программы Flash Player и Adobe AIR во время выполнения осуществляют проверку информации о типе, повышая безопасность системных типов. Информация о типе также используется для представления переменных в исходном двоичном представлении, что повышает производительность и снижает потребление памяти. Запечатанные классы
В ActionScript 3.0 представлена концепция запечатанных классов. Запечатанный класс обладает фиксированным набором свойств и методов, определенных во время компиляции; дополнительные свойства и методы к нему добавить нельзя. Это позволяет усилить контроль во время компиляции, а значит повысить надежность программ. Также оптимизируется использование памяти, поскольку для каждого экземпляра объекта не требуется отдельная внутренняя хеш-таблица. Возможно использование динамических классов с помощью ключевого слова dynamic
. Все классы в ActionScript 3.0 по умолчанию «запечатаны», но могут быть объявлены динамическими с помощью ключевого слова dynamic
.
6
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Введение в ActionScript 3.0
Закрытия методов
ActionScript 3.0 позволяет при закрытии метода автоматически запомнить исходный экземпляр объекта. Эта возможность особенно полезна при обработке событий. В ActionScript 2.0 при закрытиях методов не запоминалось, из какого экземпляра объекта они извлекались, что приводило к непредсказуемому поведению при вызове закрытия метода. Наиболее популярным обходным способом было использование класса mx.utils.Delegate, но теперь это уже не требуется. ECMAScript для XML (E4X)
В ActionScript 3.0 реализован язык сценариев ECMAScript для XML (E4X), недавно стандартизированный как ECMA-357. E4X предлагает органичный, очень удобный набор языковых конструкций для работы с XML. В отличие от стандартных прикладных интерфейсов программирования для разбора XML в языке E4X обеспечивается поддержка XML как встроенного типа данных. E4X упрощает разработку приложений, работающих с XML, значительно сокращая длину программных кодов. Дополнительные сведения о реализации E4X в ActionScript см. в разделе «Работа с XML» на странице 242. Для просмотра спецификации ECMA E4X перейдите по адресу www.ecma-international.org.
Регулярные выражения
ActionScript 3.0 включает встроенную поддержку регулярных выражений, что позволяет быстро выполнять поиск и обработку соответствующих строк. Поддержка регулярных выражений в ActionScript 3.0 реализована в соответствии с их определением в спецификации языка ECMAScript (ECMA-262) версии 3.
Пространства имен
Пространства имен аналогичны традиционным спецификаторам доступа, используемым для управления видимостью деклараций (
public
, private
, protected
). Они работают как пользовательские спецификаторы доступа, имена для которых можно задавать по своему выбору. Во избежание коллизий пространства имен задаются идентификаторами URI, которые также используются для представления пространств имен XML при работе в E4X. Новые типы примитивов
В ActionScript 2.0 был один численный тип, Number, позволявший задавать числа с плавающей точкой и с двойной точностью. ActionScript 3.0 содержит два типа: int и uint. Тип int задает 32-разрядные целочисленные значения со знаком, позволяя коду ActionScript использовать преимущество быстрой обработки целочисленных математических операций центральным процессором. Тип int удобен для создания счетчиков циклов и целочисленных переменных. Тип uint задает 32-разрядные целочисленные значения без знака, его удобно использовать для определения значений цвета RGB, байтовых счетчиков и т.д.
Возможности прикладных интерфейсов программирования Flash Player
Прикладные интерфейсы программирования (API) Flash Player в ActionScript 3.0 содержат много классов, позволяющих управлять объектами на нижнем уровне. Усовершенствована архитектура языка: она стала более удобной и понятной, чем в предыдущих версиях. Число добавленных классов слишком велико, чтобы подробно рассматривать их здесь, в следующих разделах описываются только некоторые, наиболее важные изменения. Примечание. Приложения Adobe® AIR™ также могут использовать прикладные программные интерфейсы Flash Player.
7
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Введение в ActionScript 3.0
Модель событий DOM3 Модель событий DOM3 предлагает стандартный способ создания и управления сообщениями о событиях, что позволяет обеспечить взаимодействие и обмен информацией между объектами в приложениях, отслеживая их состояние и реакцию на изменения. Настроенная в соответствии со спецификациями консорциума WWW для событий DOM третьего уровня, эта модель обеспечивает наглядный и более эффективный механизм, чем системы событий, используемые в предыдущих версиях ActionScript. События и события обработки ошибок размещаются в пакете flash.events. В структуре компонентов Adobe Flash используется та же модель событий, что и в прикладном программном интерфейсе Flash Player, поэтому система обработки ошибок едина для всей платформы Adobe Flash.
Прикладной программный интерфейс списка отображения
Прикладной программный интерфейс для доступа к списку отображения проигрывателя Flash Player и Adobe AIR — дерево, содержащее все отображаемые элементы приложения — состоит из классов для работы с визуальными примитивами.
Новый класс Sprite является облегченным конструктивным элементом, сходным с классом MovieClip, но более пригодным в качестве базового класса для компонентов пользовательского интерфейса. Новый класс Shape воспроизводит векторные фигуры без сжатия. Экземпляры этих классов легко могут создаваться с помощью оператора new
, а затем динамически переназначаться в любое время другим родительским объектам. Управление глубиной теперь осуществляется автоматически и встроено в Flash Player и Adobe AIR, так что назначение глубины при прорисовке больше не требуется. Для определения z-порядка объектов и управления ими предлагаются новые методы.
Обработка динамических данных и содержимого
ActionScript 3.0 содержит механизмы для загрузки ресурсов и данных в приложение с последующей их обработкой. Эти механизмы интуитивно понятны и согласованы с различными прикладными программными интерфейсами. Новый класс Loader предлагает единый механизм для загрузки SWF-файлов и графических ресурсов, а также обеспечивает способ доступа к детальной информации о загруженном содержимом. Класс URLLoaderпредлагает отдельный механизм для загрузки текстовых и двоичных данных в управляемые данными приложения. Класс Socket предлагает средства для считывания и записи двоичных данных в серверные сокеты в любом формате.
Доступ к данным на нижнем уровне
Различные прикладные программные интерфейсы обеспечивают доступ к данным нижнего уровня, который раньше в ActionScript был невозможен. Для данных, которые были загружены, класс URLStream, реализуемый с помощью URLLoader, обеспечивает доступ к несжатым двоичным данным непосредственно в процессе загрузки. Класс ByteArray позволяет оптимизировать чтение, запись и работу с двоичными данными. Новый прикладной интерфейс программирования звука обеспечивает точное управление звуком с помощью классов SoundChannel и SoundMixer. Новые прикладные программные интерфейсы взаимодействуют с системами безопасности, предоставляя информацию о соответствующих привилегиях SWF-файла или загруженного содержимого, позволяя лучше обрабатывать ошибки в системе безопасности.
Работа с текстом
В ActionScript 3.0 входит пакет flash.text, содержащий все связанные с обработкой текста прикладные программные интерфейсы. Класс TextLineMetrics предлагает подробные метрики для строк текста в текстовом поле; он заменил метод TextFormat.getTextExtent()
, использовавшийся в ActionScript 2.0. Класс TextField содержит ряд интересных новых методов низкого уровня, обеспечивающих специфическую информацию о строке текста или об отдельном символе в текстовом поле. В число этих методов входят: метод 8
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Введение в ActionScript 3.0
getCharBoundaries()
, который возвращает прямоугольник, отражающий границы поля символа; метод getCharIndexAtPoint()
, который возвращает индекс символа в указанной точке; а также метод getFirstCharInParagraph()
, который возвращает индекс первого символа в параграфе. К методам работы на уровне строк относятся метод getLineLength()
, возвращающий число символов в указанной строке текста, и метод getLineText()
, который возвращает текст из указанной строки. Новый класс Font обеспечивает средства для управления встроенными шрифтами в SWF-файлах.
Совместимость с предыдущими версиями
Как обычно проигрыватель Flash Player обеспечивает полную обратную совместимость с ранее опубликованным содержимым. Любое содержимое, которое выполнялось в предыдущих версиях проигрывателя Flash Player, выполняется и в Flash Player 9, а также в более поздних версиях. Появление поддержки ActionScript 3.0 в проигрывателе Flash Player 9 в то же время создает некоторые проблемы во взаимодействии между старым и новым содержимым, выполняемым в Flash Player 9 и более поздних версиях. В число проблем взаимодействия входят следующие:
•
Отдельный SWF-файл не может объединять программные коды на языках ActionScript 1.0 или 2.0 с программными кодами ActionScript 3.0.
•
Программный код ActionScript 3.0 может загрузить SWF-файл, написанный в ActionScript 1.0 или 2.0, но из него будут недоступны переменные и функции этого SWF-файла.
•
SWF-файлы, написанные в ActionScript 1.0 или 2.0, не могут загружать SWF-файлы, написанные в ActionScript 3.0. Это означает, что SWF-файлы, созданные в Adobe Flash 8 или Flex Builder 1.5, а также в более ранних версиях этих программ, не смогут загружать SWF-файлы в ActionScript 3.0.
Единственным исключением из этого правила является то, что SWF-файл ActionScript 2.0 может заменить себя SWF-файлом ActionScript 3.0, если для этого SWF-файла ActionScript 2.0 не выполнялась какая-либо загрузка ни на один из его уровней. В SWF-файле ActionScript 2.0 это можно выполнить с помощью вызова loadMovieNum()
, передав значение 0 параметру level
.
•
В общем случае для SWF-файлов, написанных в ActionScript 1.0 или 2.0, необходимо выполнять перенос, если их предполагается использовать совместно с SWF-файлами ActionScript 3.0. Например, предположим, создается проигрыватель мультимедийных данных с помощью ActionScript 2.0. Этот проигрыватель загружает различное содержимое, которое также было создано с помощью ActionScript 2.0. Нельзя создать новое содержимое в ActionScript 3.0 и загрузить его в этот проигрыватель мультимедийных данных. Необходимо выполнить перенос видеопроигрывателя в ActionScript 3.0.
Однако, если проигрыватель мультимедийных данных создан в ActionScript 3.0, он сможет выполнять отдельные загрузки содержимого ActionScript 2.0.
В следующих таблицах показаны ограничения предыдущих версий проигрывателя Flash Player в отношении загрузки нового содержимого и выполнения программного кода, а также ограничения для взаимодействия между сценариями в SWF-файлах, написанных в различных версиях ActionScript.
Поддерживаемые функции Flash Player 7 Flash Player 8 Flash Player 9 и 10
Может загружать SWF-файлы, опубликованные для
7 или более ранней версии 8 или более ранней версии 9 (или 10) и более ранних
Содержит этот AVM AVM1 AVM1 AVM1 и AVM2
Выполняет SWF-файлы, записанные в ActionScript
1.0 и 2.0 1.0 и 2.0 1.0, 2.0 и 3.0
9
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Введение в ActionScript 3.0
В следующей таблице «Поддерживаемые функции» относится к содержимому, выполняемому в проигрывателях Flash Player 9 или более поздней версии. Содержимое, выполняемое в проигрывателе Adobe Flash Player 8 или более ранней версии, может быть загружено, просмотрено и выполнено, а также использоваться при вызове из других сценариев только в ActionScript 1.0 и 2.0.
Поддерживаемые функции Содержимое, созданное в ActionScript 1.0 и 2.0
Содержимое, созданное в ActionScript 3.0
Может загружать и выполнять программный код в содержимом, созданном в
ActionScript 1.0 и 2.0 ActionScript 1.0 и 2.0, а также ActionScript 3.0
Может вызывать из сценариев содержимое, созданное в ActionScript 1.0 и 2.0 (ActionScript 3.0 через LocalConnection)
ActionScript 1.0 и 2.0 через LocalConnection.
ActionScript 3.0
10
Глава 3. Начало работы с языком ActionScript
Информация, приведенная в настоящей главе, необходима для начала программирования на языке ActionScript, а также для понимания основных концепций и примеров, приведенных в конце этого руководства. В начале главы будут рассмотрены основные концепции программирования в контексте того, как они применяются в ActionScript. Далее будут освещены наиболее важные вопросы организации и создания приложения ActionScript.
Основы программирования
Поскольку ActionScript является языком программирования, для его изучения необходимо понимание ряда основных концепций, используемых при создании компьютерных программ.
Какие функции выполняют компьютерные программы
Прежде всего необходимо понять, что представляют собой компьютерные программы и какие функции они выполняют. Существует два основных свойства компьютерной программы.
•
Программа представляет собой серию инструкций или шагов, которые должен выполнить компьютер.
•
Каждый шаг в конечном счете приводит к управлению определенной порцией информации или данных.
В общем смысле, компьютерная программа — это пошаговые инструкции, которые задаются компьютеру оператором и которые компьютер выполняет одну за другой. Каждое отдельное указание называется инструкцией. Как будет показано далее, в ActionScript каждая инструкция при записи заканчивается точкой с запятой.
В сущности, все функции отдельной инструкции программы сводятся к управлению несколькими битами информации, хранящимися в памяти компьютера. В упрощенном случае можно дать инструкцию компьютеру сложить два числа и сохранить результат в памяти. В более сложном случае можно представить себе прямоугольник, нарисованный на экране, и написать программу для перемещения его в другую часть экрана. Компьютер отслеживает определенную информацию о прямоугольнике — координаты его положения «x» и «y», ширину, высоту, цвет и т. п. Каждый бит этой информации хранится в памяти компьютера. Программа перемещения прямоугольника в другую область экрана должна включать такие пошаговые команды, как: «заменить координату «x» на 200; заменить координату «y» на 150» (другими словами, задаются новые значения координат «x» и «y»). Конечно, компьютер обрабатывает эту информацию и превращает цифры в изображение на экране монитора, однако на данном уровне рассмотрения достаточно знать, что процесс перемещения прямоугольника по экрану фактически определяется изменением битов информации, хранящихся в памяти компьютера.
11
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Переменные и постоянные
Поскольку программирование предполагает изменение информации в памяти компьютера, необходимо каким-то образом представлять отдельные порции информации в программе. Переменная является именем, которое представляет значение в памяти компьютера. При записи инструкций для управления значениями имя переменной записывается вместо значения. Когда компьютер обнаруживает имя переменной в программе, он обращается к своей памяти и использует то значение, которое там находится. Например, если есть две переменные с именами value1
(значение 1) и value2
(значение 2), каждая из которых содержит число, тогда для сложения этих чисел можно написать следующую инструкцию:
value1 + value2
При практическом выполнении этих шагов компьютер найдет значения для каждой переменной и сложит их вместе.
В ActionScript 3.0 переменная фактически состоит из трех различных частей:
•
имени переменной
•
типа данных, которые могут быть сохранены в переменной
•
фактического значения, сохраненного в памяти компьютера
Только что было рассмотрено, как компьютер использует имя в качестве местозаполнителя значения. Тип данных также важен. При создании переменной в ActionScript указывается тип данных, которые она будет содержать. После этого инструкции программы могут содержать только данный тип данных в переменной, а управлять значением можно с помощью специальных характеристик, связанных с этим типом данных. Для создания переменной в ActionScript (этот процесс называется также объявлением или заданием переменной) используется инструкция var
:
var value1:Number;
В этом случае компьютеру дается команда создать переменную value1
, которая содержит только числовые данные («Number» (число) — специальный тип данных в ActionScript). Можно также сохранить значение прямо в переменной:
var value2:Number = 17;
В Adobe Flash CS4 Professional есть другой способ задания переменной. При размещении символа фрагмента ролика, символа кнопки или текстового поля в рабочей области можно задать для них имя экземпляра в инспекторе свойств. Flash автоматически создает переменную с тем же именем, что и имя экземпляра, которое можно использовать в коде ActionScript для обращения к элементу рабочей области. Например, если в рабочей области есть символ фрагмента ролика, которому присвоено имя экземпляра rocketShip
, тогда при каждом использовании в коде ActionScript переменной rocketShip
фактически будет происходить управление этим фрагментом ролика.
Постоянная очень похожа на переменную в том смысле, что она является именем, представляющим значение с определенным типом данных в памяти компьютера. Разница состоит в том, что для постоянной значение присваивается только один раз во время выполнения приложения ActionScript. Если постоянной присвоено значение, оно больше не изменяется в приложении. Синтаксис задания постоянной аналогичен тому, который используется для переменной, за исключением использования ключевого слова const
вместо ключевого слова var
.
const SALES_TAX_RATE:Number = 0.07;
12
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Постоянная используется для определения значений, которые задействованы на многих стадиях проекта и которые не изменяются при нормальных обстоятельствах. Использование постоянных вместо литеральных значений делает код более удобочитаемым. Например, легче понять смысл строки кода, в которой цена умножается на SALES_TAX_RATE
, по сравнению со строкой, в которой цена умножается на 0.07
. Кроме того, если значение, определенное постоянной, все же требуется изменить, а постоянная, представляющая это значение, используется на протяжении всего проекта, тогда достаточно изменить это значение только в одном месте (задание постоянной) вместо замены в различных местах, как это происходит при использовании жестко запрограммированных литеральных значений.
Типы данных
В ActionScript существует много типов данных, которые можно использовать при создании переменных. Некоторые из них считаются простыми или фундаментальными типами данных:
•
Строки: текстовые значения, такие как имя или текст главы книги
•
Числовые: ActionScript 3.0 включает три специфических типа числовых данных:
•
Number: любые целые или дробные числовые значения
•
int: целые числа без дробей
•
uint: беззнаковые (не отрицательные) целые числа
•
Логические: значения типа «истинно — ложно», такие как состояния выключателя или равенство или неравенство двух значений
Простые типы данных представляют единичные порции информации: например, одно число или единичный текст. Тем не менее, большую часть типов данных в ActionScript следует рассматривать как комплексные, поскольку они представляют сгруппированные наборы значений. Например, переменная с типом данных Date (Дата) представляет единичное значение — момент времени. Тем не менее, значение даты фактически включает в себя несколько значений: день, месяц, год, час, минуты, секунды и т. д., все из которых являются отдельными числами. Таким образом, если дата рассматривается как единичное значение (и используется как единичное значение при создании переменной Date), то компьютер при внутренней обработке принимает ее за группу отдельных значений, которые, взятые вместе, определяют единичную дату.
Большинство встроенных типов данных, так же как и большинство типов данных, задаваемых программистами, являются комплексными. Некоторые из комплексных типов данных, возможно, уже знакомы многим:
•
MovieClip: символ фрагмента ролика
•
TextField: динамическое или вводимое текстовое поле
•
SimpleButton: символ кнопки
•
Date: информация о единичном моменте времени (дата и время)
Двумя широко распространенными синонимами для обозначения типа данных являются класс и объект. Класс — это просто определение типа данных. Он подобен шаблону для всех объектов с данным типом данных. Класс показывает, что все переменные экземпляра типа данных имеют определенные характеристики, например: A, B и C. Объект, с другой стороны, является фактическим экземпляром класса; переменная, тип данных которой, допустим, MovieClip, может быть описана как объект MovieClip. Ниже одна и та же мысль выражена различными словами.
•
Типом данных переменной myVariable
является Number (число).
•
Переменная myVariable
является экземпляром Number.
•
Переменная myVariable
является объектом Number.
13
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
•
Переменная myVariable
является экземпляром класса Number.
Работа с объектами
ActionScript известен как язык программирования, ориентированный на объекты. Ориентация на объекты — это всего лишь один из подходов в программировании, один из способов организации кода программы с использованием объектов.
Ранее было определено, что компьютерная программа — это серия шагов или инструкций, которые должен выполнить компьютер. Теоретически можно представить компьютерную программу как один длинный список инструкций. Тем не менее, в программировании с ориентацией на объекты инструкции разделяются между различными объектами — код группируется в функциональные блоки. При этом соответствующие типы функций или соответствующие блоки информации группируются в один контейнер. Те, кому приходилось работать с символами в Flash, фактически уже знают, как работать с объектами. Представьте себе определенный символ фрагмента ролика — пусть это будет рисунок прямоугольника, копия которого помещена в рабочую область. Этот символ фрагмента ролика является также (буквально) объектом ActionScript или экземпляром класса MovieClip. Существует несколько характеристик фрагмента ролика, которые можно изменить. Например, когда он выделен, в инспекторе свойств появляются изменяемые значения, такие как координата x, ширина, различные цветовые коррекции, параметр alpha (прозрачность) или опции фильтра наложения тени. Другие инструменты Flash позволяют осуществлять дополнительные изменения; например, инструмент «Свободное преобразование» выполняет поворот прямоугольника. Все эти модификации символа фрагмента ролика, которые можно выполнять в среде Flash, возможны и в ActionScript при изменении порций данных, объединенных в отдельный пакет, называемый объектом MovieClip.
В ориентированном на объекты языке программирования ActionScript существует три типа характеристик, которые могут входить в любой класс:
•
Свойства
•
Методы
•
События
Все вместе эти элементы используются для управления порциями данных, которые задействованы в программе, и для решения, какие действия должны быть выполнены и в каком порядке.
Свойства
Свойство представляет собой одну из порций данных, упакованную в объект. Если объектом является музыкальная композиция, ее свойствами могут быть: artist
(имя исполнителя) и title
(название). Класс MovieClip имеет такие свойства, как: rotation
(поворот), x
, width
(ширина) и alpha
(прозрачность). Работать со свойствами можно так же, как и с отдельными переменными. Фактически свойства можно рассматривать как «дочерние» переменные, содержащиеся в объекте. Ниже приведены примеры кодов ActionScript, в которых используются свойства. Эта строка кода перемещает MovieClip с именем square
(квадрат) по оси X на 100 пикселов.
square.x = 100;
Этот код использует свойство rotation для поворота MovieClip square
в соответствии с поворотом MovieClip triangle
(треугольник):
14
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
square.rotation = triangle.rotation;
Этот код изменяет горизонтальный масштаб MovieClip square
таким образом, что его ширина увеличивается в полтора раза:
square.scaleX = 1.5;
Отметьте общую структуру: переменная (
square
, triangle
) используется как имя объекта, после которого ставится точка (
.
), а затем следует имя свойства (
x
, rotation
, scaleX
). Точка, известная как оператор точки, используется для указания на доступ к одному из дочерних элементов объекта. Полная структура: «имя переменной — точка — имя свойства» используется в качестве одной переменной, как имя единичного значения в памяти компьютера.
Методы
Метод — это действие, которое может быть выполнено объектом. Например, если имеется символ фрагмента ролика в Flash с различными ключевыми кадрами и анимацией на временной шкале, тогда возможно воспроизвести или остановить этот фрагмент ролика, а также дать команду воспроизводящей головке перейти на заданный кадр.
Этот код дает команду фрагменту ролика с именем shortFilm
начать воспроизведение:
shortFilm.play();
Эта строка останавливает воспроизведение фрагмента ролика с именем shortFilm
(воспроизводящая головка останавливается, аналогично режиму паузы при воспроизведении видеофильма):
shortFilm.stop();
Этот код дает команду для фрагмента ролика с именем shortFilm
переместить воспроизводящую головку на кадр 1 и остановить воспроизведение (аналогично обратной перемотке видеофильма):
shortFilm.gotoAndStop(1);
Как видно из примеров, доступ к методам, также как и к свойствам, осуществляется путем записи имени объекта (переменной), за которым следуют точка, имя метода и скобки. Скобки указывают на вызов метода, то есть дают команду объекту для выполнения действия. Иногда в скобках помещаются значения (или переменные) для передачи дополнительной информации, которая необходима для выполнения действия. Эти значения называются параметрами метода. Например, для метода gotoAndStop()
требуется информация о том, к какому кадру следует перейти, поэтому в скобках необходимо указать единичный параметр. Другие методы, такие как play()
и stop()
, являются очевидными и не требуют дополнительной информации. Тем не менее, они также пишутся со скобками.
В отличие от свойств (и переменных), методы не используются в качестве местозаполнителя значения. Тем не менее, некоторые методы могут выполнять вычисления и возвращать результат, который можно использовать в качестве переменной. Например, метод числового класса toString()
конвертирует числовое значение в его текстовое представление:
var numericData:Number = 9; var textData:String = numericData.toString();
В частности, можно использовать метод toString()
для отображения значения числовой переменной в текстовом поле на экране. Свойство класса TextField text
(которое представляет фактический текст на экране) определено как String, поэтому оно может содержать только текстовые значения. Эта кодовая строка конвертирует числовое значение переменной numericData
в текст, а затем отображает его на экране в объекте TextField с именем calculatorDisplay
:
calculatorDisplay.text = numericData.toString();
15
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
События
Как уже было сказано ранее, компьютерная программа — это серия пошаговых инструкций, которые должен выполнить компьютер. Некоторые простые программы действительно не содержат ничего более, кроме нескольких шагов, после выполнения которых компьютером программа заканчивается. Тем не менее, программы ActionScript разработаны таким образом, что они продолжают работать, ожидая введения данных пользователем или каких-либо других событий. События являются механизмом, определяющим, когда и какие инструкции должен выполнять компьютер.
В сущности, события — это все то, что происходит, о чем ActionScript «знает» и на что может ответить. Многие события связаны с действиями пользователя, такими как нажатие экранной кнопки или клавиши клавиатуры. Однако есть и другие типы событий. Например, если ActionScript используется для загрузки внешнего изображения, существует событие, которое позволит пользователю узнать о завершении загрузки. В общих словах, при выполнении программы ActionScript проигрыватель Adobe Flash Player и среда Adobe AIR ожидают, когда произойдет определенное событие, и когда это событие происходит, они запускают соответствующий код ActionScript, который специально для этого подготовил программист.
Основные сведения об обработке событий
Техника задания определенных действий, которые необходимо выполнить в ответ на определенное событие, называется обработкой события. При написании кода ActionScript для обработки события необходимо определить три важных элемента.
•
Источник события: в каком объекте должно произойти событие? Например, какая кнопка будет нажата или какой объект Loader загружает изображение? Источник события называется также целью события, поскольку это объект, события в котором отслеживаются проигрывателем Flash Player или AIR (то есть объект, в котором событие реально происходит).
•
Событие: что именно должно произойти и на что именно требуется ответить? Это очень важно выяснить, поскольку многие объекты приводят к возникновению нескольких событий.
•
Ответ: какие шаги необходимо выполнить, когда событие произойдет?
Всякий раз при написании кода ActionScript для обработки событий необходимо включать эти три элемента. Код должен соответствовать этой основной структуре (элементы, выделенные жирным шрифтом, являются местозаполнителями, которые заполняются в зависимости от конкретного случая).
function eventResponse(eventObject:EventType):void { // Actions performed in response to the event go here. } eventSource.addEventListener(EventType.EVENT_NAME, eventResponse);
Этот код выполняет две функции. Во-первых, определяет функцию, то есть способ задания действий, которые требуется выполнить в ответ на событие. Во-вторых, вызывает метод addEventListener()
объекта источника, то есть «приписывает» функцию к определенному событию таким образом, что, когда событие произойдет, действия функции начнут выполняться. Эти две задачи будут рассмотрены более детально.
Функция обеспечивает способ для группирования действий под одним именем. То есть создается имя быстрого вызова для выполнения действий. Функция идентична методу, за исключением того, что она обязательно связана с определенным классом. Фактически методом можно назвать функцию, относящуюся к специфическом у классу. При создании функции для обработки события необходимо выбрать для нее имя (в данном случае имя функции eventResponse
). Можно также задать один параметр (названный в этом примере eventObject
). Указание параметра функции аналогично заданию переменной, поэтому требуется указать также и тип данных параметра. (В этом примере тип данных параметра: EventType
). 16
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Каждый тип событий, которые требуется отслеживать, имеет соответствующий класс в ActionScript. Тип данных, указанный для параметра функции, всегда связан с классом определенного события, на которое требуется ответить. Например, событие click
(запускаемое, когда пользователь щелкает по какому-либо пункту кнопкой мыши) связан с классом MouseEvent (события мыши). Для записи функции listener (прослушивателя) для события click
задается параметр этой функции с типом данных MouseEvent. И наконец, в фигурных скобках (
{
... }
) записываются инструкции, которые должен выполнить компьютер при наступлении события.
После записи функции обработки события необходимо сообщить объекту-источнику события (объекту, в котором происходит событие, например кнопке) о необходимости вызова функции при наступлении события. Это делается вызовом метода addEventListener()
этого объекта (все объекты, имеющие события, имеют также метод addEventListener()
. В методе addEventListener()
используются два параметра.
•
Во-первых, имя определенного события, на которое требуется ответить. Здесь также каждое событие связано с определенным классом, и этот класс будет иметь специальное значение, предопределенное для каждого события — своего рода уникальное имя события, которое используется в качестве первого параметра.
•
Во-вторых, имя функции ответа на событие. Обратите внимание, что имя функции пишется без скобок, когда оно передается как параметр.
Анализ процесса обработки события
Ниже приводится пошаговое описание процесса, возникающего при создании прослушивателя события (event listener). Это пример создания функции listener, которая вызывается при щелчке мыши по объекту с именем myButton
.
Фактический код, написанный программистом, таков:
function eventResponse(event:MouseEvent):void { // Actions performed in response to the event go here. } myButton.addEventListener(MouseEvent.CLICK, eventResponse);
Здесь рассматривается, как этот код будет реально работать с проигрывателем Flash Player. (Это поведение также относится к среде Adobe AIR.)
1
При загрузке SWF-файла проигрыватель Flash Player регистрирует факт наличия функции с именем eventResponse()
. 17
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
2
Затем проигрыватель Flash Player выполняет код (в частности, те строки кода, которых нет в функции). В данном случае это только одна строка кода: вызов метода addEventListener()
объекта-источника события (с именем myButton
) и передача функции eventResponse
как параметра.
a
Внутри объекта myButton
содержится список функций, которые следят за каждым из его событий, поэтому когда вызывается его метод addEventListener()
, myButton
сохраняет функцию eventResponse()
в своем списке прослушивателей события.
3
В какой-то момент пользователь, щелкая кнопкой мыши по объекту myButton
, запускает его событие click
(определенное в коде как MouseEvent.CLICK
).
18
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
В этот момент происходит следующее:
a
Проигрыватель Flash Player создает объект, экземпляр класса, связанного с данным событием (в этом примере — MouseEvent). Для многих событий это будет экземпляр класса Event; для событий мыши это будет экземпляр MouseEvent; для других событий это будет экземпляр класса, связанного с этим событием. Этот созданный объект называется event object. Он содержит специфическую информацию о происшедшем событии: тип, где оно произошло и другие данные, если они применимы.
b
Затем проигрыватель Flash Player обращается к списку прослушивателей, сохраненному объектом myButton
. Он перебирает эти функции одну за другой, вызывает их и передает объект события в функцию в качестве параметра. Поскольку функция eventResponse()
является одним из прослушивателей объекта myButton
, как часть этого процесса проигрыватель Flash Player вызывает функцию eventResponse()
.
19
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
c
При вызове функции eventResponse()
начинает выполняться ее код, осуществляя тем самым действия, заданные пользователем.
Примеры обработки событий
Ниже приведены несколько конкретных примеров событий, которые помогут получить представление об общих элементах и доступных вариациях при написании кода обработки события:
•
Нажатие кнопки для запуска воспроизведения текущего фрагмента ролика. В следующем примере именем экземпляра кнопки является playButton
; this
— специальное имя, означающее «текущий объект»:
this.stop(); function playMovie(event:MouseEvent):void { this.play(); } playButton.addEventListener(MouseEvent.CLICK, playMovie);
•
Обнаружение текста в текстовое поле. В этом примере entryText
является входным текстовым полем, а outputText
— динамическим текстовым полем:
function updateOutput(event:TextEvent):void { var pressedKey:String = event.text; outputText.text = "You typed: " + pressedKey; } entryText.addEventListener(TextEvent.TEXT_INPUT, updateOutput);
•
Нажатие кнопки для перехода по адресу URL: В этом случае linkButton
является именем экземпляра кнопки:
function gotoAdobeSite(event:MouseEvent):void { var adobeURL:URLRequest = new URLRequest("http://www.adobe.com/"); navigateToURL(adobeURL); } linkButton.addEventListener(MouseEvent.CLICK, gotoAdobeSite);
20
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Создание экземпляров объекта
Само собой разумеется, что перед использованием объекта в ActionScript необходимо, чтобы этот объект существовал. Одним из этапов создания объекта является задание переменной, однако эта операция создает только свободную ячейку в памяти компьютера. Необходимо задать фактическое значение переменной (то есть создать объект и сохранить его в переменной), перед тем как использовать ее или управлять ею. Процесс создания объекта называется приписыванием значения объекту, другими словами, это — создание экземпляра определенного класса.
Один простой способ создания экземпляра объекта вообще не требует использования ActionScript. В Flash при размещении символа фрагмента ролика, символа кнопки или текстового поля в рабочей области, если в инспекторе свойств задано имя экземпляра, Flash автоматически задает переменную с именем экземпляра, создает экземпляр объекта и сохраняет этот объект в переменной. Аналогичным образом, когда в Adobe Flex Builder создается компонент в MXML (либо кодированием тега MXML, либо размещением компонента в редакторе в режиме Design), и когда этому компоненту приписывается идентификатор (в разметке MXML или в обзоре свойств Flex), этот идентификатор становится именем переменной ActionScript, а экземпляр компонента создается и сохраняется в переменной.
Тем не менее, визуальное создание объекта не всегда устраивает пользователя. Существует также несколько способов создания экземпляров объекта исключительно с помощью ActionScript. Во-первых, с помощью различных типов данных ActionScript можно создавать экземпляры, используя литеральное выражение, — значение, записываемое непосредственно в код ActionScript. Примеры:
•
Литеральное числовое значение (непосредственный ввод числа):
var someNumber:Number = 17.239; var someNegativeInteger:int = -53; var someUint:uint = 22;
•
Литеральное строчное значение (текст, заключенный в двойные кавычки):
var firstName:String = "George"; var soliloquy:String = "To be or not to be, that is the question...";
•
Литеральное логическое значение (используются значения истинно/ложно — true
или false
):
var niceWeather:Boolean = true; var playingOutside:Boolean = false;
•
Литеральный массив значений (список разделенных запятой значений в квадратных скобках):
var seasons:Array = ["spring", "summer", "autumn", "winter"];
•
Литеральное значение XML (непосредственный ввод XML):
var employee:XML = <employee> <firstName>Harold</firstName> <lastName>Webster</lastName> </employee>;
В ActionScript определяются также литеральные выражения для следующих типов данных: Array, RegExp, Object и Function. Подробные сведения об этих классах приведены в разделах: «Работа с массивами» на странице 167, «Использование регулярных выражений» на странице 221 и «Тип данных Object» на странице 66.
Чтобы создать экземпляр объекта с другим типом данных, используется оператор new
с именем класса:
var raceCar:MovieClip = new MovieClip(); var birthday:Date = new Date(2006, 7, 9);
21
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Создание объекта с помощью оператора new
часто называется «вызовом конструктора класса». Конструктор — это специальный метод, который является частью процесса создания экземпляра класса. Обратите внимание, что когда экземпляр создается этим способом, после имени класса ставятся скобки, в которых иногда задаются значения параметра, — эти две операции делаются всегда при вызове метода.
Обратите внимание, что даже для тех типов данных, которые позволяют создавать экземпляры с помощью литерального выражения, все равно можно создавать экземпляр объекта, используя оператор new
. Например, эти две строки кода дают совершенно одинаковый результат:
var someNumber:Number = 6.33; var someNumber:Number = new Number(6.33);
Очень важно приобрести опыт в создании объектов с помощью метода new ClassName
()
. Если требуется создать экземпляр какого-либо типа данных ActionScript, который не имеет визуального представления (и следовательно, не может быть создан путем размещения элемента в рабочей области Flash или в режиме Design редактора MXML Flex Builder), тогда сделать это можно путем создания объекта непосредственно в ActionScript с помощью оператора new
.
В частности, в Flash можно также использовать оператор new
для создания экземпляра символа фрагмента ролика, который определен в Библиотеке, но не помещен в рабочую область. Дополнительную информацию см. в разделе «Создание объектов MovieClip с помощью ActionScript» на странице 437.
Общие элементы программы
Кроме задания переменных, создания экземпляров объектов и управления объектами с помощью их свойств и методов, существуют и другие функциональные блоки, необходимые для создания программы ActionScript.
Операторы
Операторы — это специальные символы (иногда слова), которые используются для выполнения вычислений. В основном они используются для математических операций, а также для сравнения значений друг с другом. Согласно общему правилу оператор использует одно или несколько значений и работает на единичный результат. Например:
•
Оператор сложения (
+
) складывает два значения, результатом чего является одно число:
var sum:Number = 23 + 32;
•
Оператор умножения (
*
) перемножает два значения, результатом чего также является одно число:
var energy:Number = mass * speedOfLight * speedOfLight;
•
Оператор равенства (
==
) сравнивает два значения и выдает результат в форме единичного (логического) значения истинно/ложно:
if (dayOfWeek == "Wednesday") { takeOutTrash(); }
Как здесь показано, оператор равенства и другие операторы сравнения наиболее часто используются с инструкцией if
, чтобы определить, должны выполняться определенные указания или нет.
Дополнительные сведения см. в разделе «Операторы» на странице 76.
22
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Комментарии
При написании программы в ActionScript у программиста часто возникает необходимость сделать замечания для самого себя, например, для пояснения работы кода или для объяснения, почему сделан тот или иной выбор. Комментарии кода — это инструмент, позволяющий записывать текстовую информацию, которую компьютер не будет воспринимать как команды кода. В ActionScript предусмотрено два вида комментариев.
•
Однострочный комментарий: вставляется в любое место строки и отмечается двумя косыми чертам. Все, что находится за косыми чертами до конца строки, игнорируется компьютером:
// This is a comment; it's ignored by the computer. var age:Number = 10; // Set the age to 10 by default.
•
Многострочные комментарии: состоят из начального маркера /*
, содержания комментария и конечного маркера */
. Все, что находится между начальным и конечным маркерами, игнорируется компьютером, независимо от того, сколько строк занимает комментарий.
/* This might be a really long description, perhaps describing what a particular function is used for or explaining a section of code. In any case, these lines are all ignored by the computer. */
Другим распространенным использованием комментариев является временное выключение одной или нескольких строк кода. Это необходимо, например, для проверки другого способа выполнить те же действия или для выяснения причины сбоев определенной части кода ActionScript.
Управление исполнением программы
Довольно часто при отладке программы требуется повторить отдельные действия, выполнить только выбранные действия и не выполнять другие, переключиться на альтернативные действия в зависимости от определенных условий и т. п. Управление исполнением программы предназначено для контроля выполняемых действий. В ActionScript предусмотрено несколько элементов управления исполнением программы.
•
Функции: своего рода комбинации быстрого вызова, позволяющие группировать серии действий под одним именем, используются для выполнения вычислений. Функции наиболее важны для обработки событий, однако они используются и как общий инструмент для группирования серий инструкций. Дополнительные сведения о функциях см. в разделе «Функции» на странице 87.
•
Циклы: циклические структуры, позволяющие задать набор инструкций, которые компьютер будет выполнять установленное число раз или до изменения некоторых условий. Часто циклы используются для управления несколькими связанными элементами. При этом используется переменная, значение которой изменяется каждый раз, когда компьютер выполнит один цикл. Дополнительные сведения о циклах см. в разделе «Повтор» на странице 84.
•
Условные инструкции: обеспечивают способ задавать инструкции, выполняемые только при определенных условиях, или задавать альтернативные наборы инструкций для различных условий. Наиболее распространенной условной инструкцией является инструкция if
. Инструкция if проверяет значение или выражение в скобках. Если это значение истинно — true
, тогда строка кода в фигурных скобках выполнятся, в противном случае строка игнорируется. Например:
if (age < 20) { // show special teenager-targeted content }
23
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Инструкция else
, связанная с инструкцией if
, позволяет задать альтернативные инструкции, которые выполняются, если условия не будут соответствовать требованию true
:
if (username == "admin") { // do some administrator-only things, like showing extra options } else { // do some non-administrator things }
Дополнительные сведения об условных инструкциях см. в разделе «Условия» на странице 82.
Пример: фрагмент анимации портфолио
Этот пример разработан для того, чтобы дать первую возможность программисту собрать отдельные блоки ActionScript в полную, если даже не сказать сложную программу. Фрагмент анимации портфолио является примером того, как можно использовать существующую линейную анимацию (например, фрагмент, созданный для клиента) и добавить к ней некоторые небольшие интерактивные элементы, подходящие для вставки этой анимации в онлайн-портфолио. Интерактивные элементы, добавленные к анимации, будут включать две кнопки, которые может нажимать зритель: одна для запуска анимации, другая для перехода к отдельному URL (к меню портфолио или к главной странице автора).
Процесс создания этого фрагмента будет разделен на следующие основные части:
1
Подготовка FLA-файла для добавления ActionScript и интерактивных элементов.
2
Создание и добавления кнопок.
3
Написание кода ActionScript.
4
Проверка приложения.
Подготовка и добавление интерактивных элементов
Перед добавлением интерактивных элементов к анимации следует подготовить FLA-файл, создав место для добавления нового содержания. Сюда входит создание фактического места в рабочей области, где будут размещены кнопки, а также создание «пространства» в FLA-файле для раздельного размещения отдельных элементов.
Подготовка FLA-файла к добавлению интерактивных элементов
1
Если линейная анимация, к которой будут добавлены интерактивные элементы, отсутствует, необходимо создать новый FLA-файл с простой анимацией, такой как анимация движения или анимация формы. В другом случае откройте FLA-файл, содержащий вставленную в проект анимацию, и сохраните его под новым именем для создания нового рабочего файла.
2
Выберите место на экране, где будут появляться две кнопки (одна — для запуска анимации, другая — для перехода к портфолио автора или к его главной странице). При необходимости очистите или добавьте место в рабочей области для нового содержания. Если это еще не сделано, можно создать заставку в первом кадре анимации (возможно также изменить анимацию, чтобы она начиналась с кадра 2 или более позднего).
24
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
3
Добавьте новый слой поверх других слоев на Временной шкале и присвойте ему новое имя: кнопки. В этот слой будут добавлены кнопки.
4
Добавьте новый слой поверх слоя кнопок и присвойте ему имя действия. Сюда будет добавлен код ActionScript для этого приложения.
Создание и добавление кнопок
Далее потребуется создать и разместить кнопки, которые занимают центральное место в данном интерактивном приложении.
Создание и добавление кнопок к FLA-файлу
1
Используя инструменты рисования, создайте в слое кнопок визуальный образ первой кнопки («воспроизведение»). Например, можно нарисовать горизонтальный овал с текстом по его верхнему краю.
2
Используя инструмент выделения, выделите все графические части кнопки.
3
В главном меню выберите команды «Модификация» > «Преобразовать в символ».
4
Выберите в диалоговом окне в качестве типа символа «Кнопка», присвойте символу имя и нажмите «ОК».
5
При выделенной кнопке в инспекторе свойств присвойте ей имя экземпляра playButton.
6
Повторите шаги 1—5 для создания аналогичной кнопки для перехода к главной странице автора. Имя этой кнопки: homeButton.
Написание кода
Код ActionScript для этого приложения можно разделить на три функциональных блока, несмотря на то что он вводится в одном месте. Код нужен для выполнения следующих трех операций:
•
Остановить воспроизводящую головку сразу после загрузки SWF-файла (в тот момент, когда воспроизводящая головка подойдет к Кадру 1).
•
Следить за событием, чтобы запустить воспроизведение SWF-файла при нажатии зрителем кнопки воспроизведения.
•
Следить за событием, чтобы отправить обозреватель на соответствующий URL-адрес при нажатии зрителем кнопки главной страницы. Создание кода остановки воспроизводящей головки в начале Кадра 1
1
Выберите ключевой кадр для Кадра 1 в слое действий.
2
Чтобы открыть панель «Действия», выберите в главном меню команды «Окно» > «Действия».
3
На панели «Сценарий» введите следующий код:
stop();
Запись кода запуска анимации при нажатии кнопки воспроизведения
1
Добавьте две пустые строки в конце кода предыдущего шага.
2
Введите следующий код в нижней части сценария:
function startMovie(event:MouseEvent):void { this.play(); }
25
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Код определяет функцию с именем startMovie()
. При вызове функция startMovie()
запускает временную шкалу и начинает воспроизведение.
3
На строке, следующей за кодом, добавленным на предыдущем шаге, введите следующую строку кода:
playButton.addEventListener(MouseEvent.CLICK, startMovie);
Эта строка кода регистрирует функцию startMovie()
как прослушивателя события click
для кнопки playButton
. Другими словами, код определяет, что при нажатии кнопки с именем playButton
вызывается функция startMovie()
.
Запись кода отправки обозревателя на URL-адрес при нажатии кнопки главной страницы
1
Добавьте две пустые строки в конце кода предыдущего шага.
2
Введите следующий код в нижней части сценария:
function gotoAuthorPage(event:MouseEvent):void { var targetURL:URLRequest = new URLRequest("http://example.com/"); navigateToURL(targetURL); }
Код определяет функцию с именем gotoAuthorPage()
. Эта функция сначала создает экземпляр URLRequest, представляющий URL http://example.com/, а затем передает этот URL функции navigateToURL()
, заставляя обозреватель пользователя открыть этот URL.
3
На строке, следующей за кодом, добавленным на предыдущем шаге, введите следующую строку кода:
homeButton.addEventListener(MouseEvent.CLICK, gotoAuthorPage);
Эта строка кода регистрирует функцию gotoAuthorPage()
как прослушивателя события click
для кнопки homeButton
. Другими словами, код определяет, что при нажатии кнопки с именем homeButton
вызывается функция gotoAuthorPage()
.
Проверка приложения
На этом этапе приложение должно быть полностью работоспособным. Однако чтобы убедиться в этом, его следует проверить.
Выполнение проверки приложения
1
В главном меню выберите команды «Управление» > «Тестировать ролик». Flash создает SWF-файл и открывает его в окне проигрывателя Flash Player.
2
Нажмите обе кнопки и убедитесь, что они выполняют требуемые действия.
3
Если кнопки не работают, необходимо выяснить следующее:
•
Имеют ли кнопки отдельные имена экземпляров?
•
Совпадают ли имена, используемые ли при вызове метода addEventListener()
, с именами экземпляров кнопок?
•
Используются ли корректные имена событий при вызове метода addEventListener()
?
•
Указаны ли корректные параметры для каждой из функций? (Обе функции должны иметь один параметр с типом данных MouseEvent.)
26
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Все эти и многие другие ошибки приводят к появлению сообщения об ошибке, как при выборе команды «Тестировать ролик», так и при нажатии кнопки. Ошибки компиляции отображаются на панели «Ошибки компиляции» (эти ошибки обнаруживаются при первом запуске команды «Тестировать ролик»). Ошибки при выполнении показываются на панели «Вывод» (эти ошибки обнаруживаются при воспроизведении SWF, то есть при нажатии кнопки).
Создание приложений с ActionScript
Процесс создания приложений с помощью языка ActionScript требует намного большего, чем простое знание синтаксиса и названий используемых классов. Хотя основная информация настоящего руководства посвящена именно этим вопросам (синтаксису и работе с классами ActionScript), необходимо изучить также, какие программы можно написать и переработать с помощью ActionScript, как организовать и включить код ActionScript в приложения и какую последовательность следует соблюдать при разработке приложений ActionScript.
Параметры для организации кода
С помощью ActionScript 3.0 можно усовершенствовать все что угодно, начиная от простых графических анимаций до комплексных систем обработки транзакций клиент-сервер. В зависимости от типа создаваемого приложения, можно использовать один или несколько из нижеприведенных способов включения ActionScript в проект.
Сохранение кода в кадрах временной шкалы Flash
В среде разработки Flash можно добавлять код ActionScript в любой кадр на временной шкале. Этот код будет выполняться при обратном воспроизведении ролика, когда воспроизводящая головка подходит к указанному кадру.
Размещение кода ActionScript в кадрах обеспечивает простой способ добавления свойств для приложений, встроенных в инструмент разработки Flash. Добавить код можно в любой кадр основной временной шкалы любого символа MovieClip. Тем не менее, эта функциональная гибкость связана с некоторыми неудобствами. При создании объемных приложений становится трудно отслеживать взаимосвязь кадров и содержащихся в них сценариев. Это усложняет процесс обслуживания приложения с течением времени.
Многие разработчики упрощают организацию кода ActionScript в инструменте разработки Flash, размещая код только в первом кадре временной шкалы или в специальном слое документа Flash. Это упрощает размещение и обслуживание кода в FLA-файлах Flash. Тем не менее, для использования кода в другом проекте Flash необходимо скопировать и вставить код в новый файл.
Если требуется впоследствии использовать код в другом проекте Flash, необходимо сохранить код во внешних файлах ActionScript (то есть в текстовых файлах с расширением .as).
27
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Сохранение кода в файлах ActionScript Если проект включает объемный код ActionScript, лучше всего разместить этот код в отдельных исходных файлах ActionScript (то есть в текстовых файлах с расширением .as). Файл ActionScript можно структурировать одним из двух способов в зависимости от характера его использования в приложении.
•
Неструктурированный код ActionScript: строки кода, включающие инструкции или функциональные определения, которые написаны так, как если бы они вводились непосредственно в сценарий временной шкалы, MXML-файл и т. п.
Сценарий ActionScript, написанный таким образом, доступен с помощью инструкции include
в ActionScript или с помощью тега <mx:Script>
в Adobe Flex MXML. Инструкция ActionScript include
позволяет вставить содержимое внешнего файла ActionScript в специальное место сценария внутри заданных границ, как если бы оно было введено туда непосредственно. Тег <mx:Script>
в языке Flex MXML позволяет задать исходный атрибут, определяющий внешний файл ActionScript, который должен быть загружен в этом пункте в приложение. Например, следующий тег загружает внешний файл ActionScript с именем Box.as:
<mx:Script source="Box.as" />
•
Определение класса ActionScript: определение класса ActionScript, включая определение его метода и свойства.
При определении класса доступ к коду ActionScript осуществляется путем создания экземпляра класса с использованием его свойств, методов и событий, так же как это делается при встраивании классов ActionScript. Это делается в два этапа:
•
Используйте инструкцию import
для задания полного имени класса, чтобы компилятор ActionScript «знал», где его найти. Например, если требуется использовать класс MovieClip в ActionScript, прежде всего необходимо импортировать этот класс, используя его полное имя, включая пакет и класс.
import flash.display.MovieClip;
Альтернативно можно импортировать пакет, содержащий класс MovieClip, что эквивалентно записи отдельных инструкций import
для каждого класса в пакете:
import flash.display.*;
Единственное исключение из этого правила состоит в том, что класс необходимо импортировать, если в коде есть ссылка на этот класс, и этот класс принадлежит к классам высшего уровня, которые не определены в пакете.
Примечание. В Flash для сценариев, прикрепленных к кадрам на временной шкале, встроенные классы (в пакетахflash.*) импортируются автоматически. Тем не менее, при записи собственных классов пользователя, при работе с компонентами разработки Flash (пакеты fl.*),а также при работе в Flex необходимо эксплицитно импортировать каждый класс, для того чтобы записать код, который создает экземпляры этого класса.
•
Запишите код, который специально относится к имени класса (обычно задается переменная с этим классом, как его тип данных, и создается экземпляр класса для сохранения в переменной). При обращении к другому имени класса в коде ActionScript компилятору дается команда загрузить определение этого класса. Например, если внешний класс называется Box, эта инструкция инициирует создание нового экземпляра класса Box.
var smallBox:Box = new Box(10,20);
Когда компилятор первый раз встречает ссылку на класс Box, он просматривает загруженный исходный код, чтобы найти определение класса Box. 28
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Правильный выбор инструмента
В зависимости от задач проекта и доступных ресурсов, для написания и редактирования кода ActionScript можно использовать один из нескольких инструментов (или несколько взаимосвязанных инструментов).
Инструмент разработки Flash
В дополнение к возможностям создания графики и анимации Adobe Flash CS4 Professional содержит инструменты для работы с кодом ActionScript, которые или присоединены к элементам FLA-файла, или содержатся в специальных внешних файлах ActionScript. Инструмент разработки Flash идеально подходит для тех проектов, которые включают объемные блоки анимации и видео, а также для тех, где большая часть графических материалов создается пользователем самостоятельно, особенно это относится к проектам с минимальной интерактивностью или функциональностью ActionScript. Другой причиной для выбора инструмента разработки Flash может быть желание создавать визуальные материалы и записывать код в одном и том же приложении. Инструмент разработки Flash можно использовать также в том случае, когда использование ранее созданных компонентов интерфейса при небольшом объеме SWF и упрощенный визуальный скиннинг являются ключевыми приоритетами проекта.
Adobe Flash CS4 Professional включает два инструмента для написания кода ActionScript:
•
Панель «Действия»: эта панель, доступная при работе с FLA-файлом, позволяет записывать код ActionScript, присоединенный к кадрам на временной шкале.
•
Окно «Сценарий»: окно сценария — это специализированный текстовый редактор для работы файлами кода ActionScript (.as).
Flex Builder
Adobe Flex Builder является главным инструментом для создания проектов в структуре Flex. В дополнение к визуальным макетам и инструментам редактирования MXML, Flex Builder также включает полнофункциональный редактор ActionScript, поэтому его можно использовать для создания как проектов Flex, так и специализированных проектов ActionScript. Приложения Flex имеют определенные преимущества, включая богатый набор встроенных средств управления интерфейсом, гибкие средства динамического управления компоновкой, встроенные механизмы для работы с внешними источниками данных и возможности связи внешних данных с элементами пользовательского интерфейса. Тем не менее, для обеспечения этих функций требуется дополнительный код, поэтому приложения Flex имеют SWF-файл увеличенного размера и не могут полностью изменить оболочку так просто, как их Flash-аналоги.
Flex Builder рекомендуется использовать для создания полнофункциональных интернет-приложений Flex с большим потоком данных, если при этом требуется редактировать коды ActionScript и MXML, а также компоновать приложение визуально, и, кроме того, выполнять все это с помощью одного инструмента.
Сторонний редактор ActionScript Поскольку файлы ActionScript (.as) сохраняются как простые текстовые файлы, для создания этих файлов можно использовать любую программу, способную редактировать простые текстовые файлы. Кроме продуктов ActionScript компании Adobe существуют различные программы с текстовыми редакторами и специальными функциями для ActionScript, созданные сторонними разработчиками. Создать файл MXML или классы ActionScript можно в любой программе с текстовым редактором. Затем с помощью набора Flex SDK, который включает классы структуры Flex и компилятор Flex, из этих файлов можно создать приложение SWF (Flex или только ActionScript). Альтернативно многие разработчики используют сторонние редакторы ActionScript для написания классов ActionScript в сочетании с инструментом разработки Flash для создания графического содержимого.
29
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Использовать редактор ActionScript сторонних компаний можно в нижеперечисленных случаях.
•
Если код ActionScript требуется написать в отдельной программе в сочетании с разработкой визуальных элементов в Flash.
•
При использовании приложения в среде программирования, отличной от ActionScript (например, создание HTML-страниц или приложений на другом языке программирования), если требуется использовать то же самое приложение для кодирования в ActionScript.
•
Если требуется создать проекты в Flex или только в ActionScript с использованием набора Flex SDK без Flash или Flex Builder.
Ниже перечислены наиболее известные редакторы кодов со специальной поддержкой ActionScript:
•
Adobe Dreamweaver® CS4
•
ASDT
•
FDT
•
FlashDevelop
•
PrimalScript
•
SE|PY
Процесс разработки в ActionScript
Независимо от объема проекта ActionScript, использование процесса проектирования и разработки приложения сделает работу более эффективной. Процесс разработки приложения в ActionScript 3.0 включает в себя следующие этапы.
1
Проектирование приложения.
Перед созданием приложения следует описать его в общих чертах.
2
Составление кода в ActionScript 3.0.
Код ActionScript создается с помощью Flash, Flex Builder, Dreamweaver или текстового редактора. 3
Создание файла приложения для выполнения кода в Flash или в Flex. В инструменте разработки Flash для этого требуется создать новый FLA-файл, задать параметры публикации, добавить к приложению компоненты пользовательского интерфейса и сделать привязку к коду ActionScript. В среде разработки Flex создание нового файла приложения включает в себя определение приложения и добавление компонентов пользовательского интерфейса с помощью MXML, а также привязку к коду ActionScript.
4
Публикация и проверка приложения ActionScript. Сюда входит выполнение приложения в среде разработки Flash или в среде разработки Flex, а также полная проверка его функциональности в соответствии с поставленными задачами.
Обратите внимание, что все действия этих этапов не обязательно выполнять в указанном порядке, не обязательно также полностью завершать один этап, прежде чем приступать к следующему. Например, можно разработать один экран приложения (этап 1), а затем создать графику, кнопки и т. д. (этап 3) до написания кода ActionScript (этап 2) и проверки (этап 4). Можно также разработать часть приложения, а затем добавлять отдельные кнопки или элементы интерфейса, создавая для каждого элемента код ActionScript и проверяя его по мере готовности. Несмотря на то, что последовательность этих четырех этапов полезно запомнить, в реальной ситуации обычно более эффективно переходить вниз или вверх по этапам, как представляется удобным.
30
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Создание пользовательских классов
Процесс создания классов для использования в пользовательском проекте кажется довольно сложным. Тем не менее, самой сложной частью в создании класса является его разработка — определение методов, свойств и событий, которые он будет включать.
Стратегия разработки класса
Тема проектирования с ориентацией на объект довольно сложна. Академическим изучением этой дисциплины и ее профессиональным применением можно заниматься всю жизнь. Тем не менее, здесь приводится несколько рекомендаций и подходов, которые помогут сделать первые шаги в этом направлении.
1
Продумайте роль, которую будут играть экземпляры этого класса в приложении. Обычно объекты выполняют одну из следующих трех функций:
•
Объекты значений: используются главным образом как контейнеры данных. Они имеют несколько свойств и методов (причем методов обычно меньше или нет совсем). Как правило, эти объекты являются кодовыми представлениями четко обозначенных элементов, таких как класс Song (представляющий одну реальную песню) или класс Playlist (представляющий схематическую группу песен) в программе музыкального проигрывателя.
•
Экранные объекты: эти объекты реально отображаются на экране. В качестве примеров можно назвать выпадающие списки, индикаторные панели состояния, графические элементы, такие как различные существа в видеоиграх и т. п.
•
Структурные объекты приложения: эти объекты выполняют широкие функции, поддерживая обработку данных и логические операции, выполняемые приложением. Примеры: объекты для вычислений в биологических моделях, объекты синхронизации значений шкалы регулятора и уровня громкости в программе музыкального проигрывателя, объекты управления правилами видеоигры или объекты загрузки и сохранения изображения в графических приложениях и т. д.
2
Определите специальные функции для данного класса. Различные функциональные типы часто становятся методами класса.
3
Если класс должен использоваться как объект значений, решите, какие данные будут содержать его экземпляры. Эти элементы являются хорошими кандидатами в свойства.
4
Поскольку класс разрабатывается специально для пользовательского проекта, очень важно снабдить его теми функциями, которые необходимы для конкретного приложения. При этом полезно ответить на следующие вопросы:
•
Какие порции информации будущее приложение будет сохранять, отслеживать и обрабатывать? Решение этого вопроса поможет определить все объекты значений и свойства, которые могут потребоваться.
•
Какой набор действий должен быть выполнен? Например: когда происходит первая загрузка приложения? Когда нажимается отдельная кнопка? Когда останавливается воспроизведение ролика? И т. д. Эти элементы являются хорошими кандидатами в методы (или свойства, если только «действия» допускают изменение отдельных значений).
•
Для каждого действия: какая информация требуется для класса, чтобы данное действие было выполнено? Эти порции информации становятся параметрами метода.
•
По мере выполнения программы, что будет изменяться в классе, о чем должны будут знать другие компоненты приложения? Эти элементы являются хорошими кандидатами в события.
31
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
5
Если существует некий объект, аналогичный тому, который требуется создать, во всем, за исключением некоторых функций, которые можно добавить, подумайте о возможности создания подкласса (то есть класса, который можно построить на функциональной основе существующего класса, вместо того чтобы задавать все функции самостоятельно). Например, если требуется создать визуальный объект на экране, можно использовать характеристики существующих экранных объектов (таких как Sprite или MovieClip) в качестве базиса для создания собственного класса. В этом случае MovieClip (или Sprite) будет базовым классом, а создаваемый класс будет расширением этого класса. Более подробно о создании подкласса см. в разделе «Наследование» на странице 118.
Написание кода для класса
После того как составлен план разработки класса или хотя бы намечены основные идеи о том, какую информацию он будет отслеживать и какие действия выполнять, фактический синтаксис написания класса выглядит довольно просто.
Ниже перечислены основные шаги создания собственного класса ActionScript:
1
Откройте новый текстовый документ в программе со специальными функциями ActionScript (такой как Flex Builder или Flash) в общем инструменте программирования, (например, Dreamweaver) или в любой программе, позволяющей работать с простыми текстовыми документами.
2
Введите инструкцию class
для задания имени класса. Для этого введите слова public class
, затем имя класса и открывающую/закрывающую пару фигурных скобок, между которыми будет расположено содержимое класса (определения методов и свойств). Например:
public class MyClass { }
Слово public
означает, что этот класс доступен для любого другого кода. Другие возможности описаны в разделе «Атрибуты пространства имен для управления доступом» на странице 103.
3
Введите инструкцию package
для задания имени пакета, в котором можно будет найти созданный класс. Синтаксис состоит из слова package
, полного имени пакета и открывающей/закрывающей пары фигурных скобок (между которыми будет расположен блок инструкции class
). Например, код предыдущего шага изменяется следующим образом:
package mypackage { public class MyClass { } }
4
Определите каждое свойство в классе, используя инструкцию var
внутри тела класса. Синтаксис остается тем же, что и при задании переменной (с добавлением модификатора public
). Например, добавление следующих строк между открывающей/закрывающей фигурными скобками определения класса приведет к созданию свойств с именами textVariable
, numericVariable
и dateVariable
:
public var textVariable:String = "some default value"; public var numericVariable:Number = 17; public var dateVariable:Date;
5
Определите каждый метод в классе с помощью синтаксиса, который использовался для задания функции. Например:
•
Для создания метода myMethod()
введите:
32
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
public function myMethod(param1:String, param2:Number):void { // do something with parameters }
•
Для создания конструктора (специального метода, который является частью процесса создания экземпляра класса), создайте метод с именем, которое в точности совпадает с именем класса:
public function MyClass() { // do stuff to set initial values for properties // and otherwise set up the object textVariable = "Hello there!"; dateVariable = new Date(2001, 5, 11); }
Если пользователь не включает метод конструктора в свой класс, компилятор автоматически создает в классе пустой конструктор (без параметров и инструкций).
Существует еще несколько элементов класса, которые может задать пользователь. Эти элементы более сложны.
•
Средства доступа — это специальные узлы связи между методом и свойством. Когда записывается код для определения класса, средство доступа записывается как метод. Таким образом, можно выполнять множественные действия (а не только чтение и задание значения — единственные действия, доступные при задании свойства). Тем не менее, при создании экземпляра класса средство доступа рассматривается как свойство — используется только его имя для чтения и задания значения. Дополнительные сведения см. в разделе «Методы доступа get и set» на странице 111.
•
События в ActionScript не задаются с помощью специального синтаксиса. Вместо этого события определяются в пользовательском классе с помощью функций класса EventDispatcher, чтобы контролировать прослушивателей события и уведомлять их о событиях. Дополнительные сведения о создании событий в пользовательских классах см. в разделе «Обработка событий» на странице 264.
Пример: создание базового приложения
Внешние исходные файлы ActionScript с расширением .as можно создавать с помощью Flash, Flex Builder, Dreamweaver или любого текстового редактора.
ActionScript 3.0 можно использовать в различных средах разработки, включая авторизованный инструмент Flash и Flex Builder. В этом разделе описаны этапы создания и модернизации простого приложения ActionScript 3.0 с использованием инструмента разработки Flash или Flex Builder. Рассматриваемое приложение служит простой моделью для использования внешних файлов классов ActionScript 3.0 в приложениях Flash и Flex. Эта модель будет использована также во всех других демонстрационных приложениях настоящего руководства.
Проектирование приложения ActionScript
Перед созданием приложения следует описать его в общих чертах.
33
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Описание проекта может быть как очень простым, содержащим имя приложения и краткое изложение его назначения, так и очень сложным, содержащим набор требуемых документов, включая многочисленные диаграммы унифицированного языка моделирования (UML). В настоящем руководстве не рассматриваются детали проектирования программного обеспечения, однако следует учесть, что составление проекта приложения является важным этапом в разработке приложения ActionScript.
Первым примером приложения ActionScript будет простая стандартная программа.
•
Называться эта программа будет «HelloWorld» (Здравствуй, мир). •
Она будет отображать единственное текстовое поле, содержащее слова «Hello World!» •
С целью повторного использования, здесь применяется отдельный, ориентированный на объект класс с именем Greeter, который можно использовать в документе Flash или приложении Flex.
•
После создания базовой версии приложения добавляются новые функции для ввода имени пользователя и проверки приложением этого имени по списку известных пользователей.
После этого краткого определения можно приступать к созданию приложения.
Создание проекта HelloWorld и класса Greeter
В проектном задании для приложения Hello World говорится, что его код должен допускать простое повторное использование. С этой целью в данном приложении используется отдельный, ориентированный на объект класс с именем Greeter, который используется внутри приложения, созданного с помощью авторизованного инструмента Flash или Flex Builder.
Создание класса Greeter с помощью инструмента разработки Flash
1
В инструменте разработки Flash выберите «Файл» > «Создать».
2
В диалоговом окне «Создать документ» выберите файл ActionScript и нажмите кнопку «ОК».
Теперь появится окно редактирования нового файла ActionScript.
3
Выберите команды «Файл» > «Сохранить». Выберите папку для размещения приложения, присвойте файлу ActionScript имя Greeter.as и нажмите кнопку «ОК».
После этого можно перейти к «Добавление кода к классу Greeter» на странице 33.
Добавление кода к классу Greeter
Класс Greeter определяет объект Greeter
, который можно будет использовать в приложении HelloWorld.
Добавление кода к классу Greeter
1
Введите следующий код в новый файл:
34
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
package { public class Greeter { public function sayHello():String { var greeting:String; greeting = "Hello World!"; return greeting; } } }
Класс Greeter включает один метод sayHello()
, который возвращает строку с фразой «Hello World!».
2
Для сохранения этого файла ActionScript выберите команды «Файл» > «Сохранить». Класс Greeter теперь готов для использования в приложении.
Создание приложения с использованием кода ActionScript
Класс Greeter, который был только что создан, определяет самодостаточный набор программных функций, однако он не представляет собой законченное приложение. Чтобы использовать этот класс, необходимо создать документ Flash или приложение Flex.
Приложение HelloWorld создает новый экземпляр класса Greeter. Ниже описывается процедура присоединения класса Greeter к создаваемому приложению.
Создание приложения ActionScript с помощью инструмента разработки Flash
1
Выберите команды «Файл» > «Создать».
2
В диалоговом окне «Создать документ» выберите документ Flash и нажмите кнопку «ОК».
После этого появится окно нового документа Flash.
3
Выберите команды «Файл» > «Сохранить». Выберите папку, в которой находится файл класса Greeter.as, присвойте документу Flash имя HelloWorld.fla и нажмите кнопку «ОК».
4
В палитре инструментов Flash выберите инструмент «Текст» и методом перетаскивания задайте в рабочей области новое текстовое поле примерно 300 пикселов длиной и 100 пикселов высотой.
5
На панели «Свойства» при все еще выделенном в рабочей области текстовом поле задайте тип текста как «Динамический текст» и введите mainText в качестве имени экземпляра текстового поля. 6
Щелкните кнопкой мыши первый кадр временной шкалы.
7
На панели «Действия» введите следующий сценарий:
var myGreeter:Greeter = new Greeter(); mainText.text = myGreeter.sayHello();
8
Сохраните файл.
После этого можно перейти к «Публикация и проверка приложения ActionScript» на странице 35.
35
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Публикация и проверка приложения ActionScript
Разработка программного обеспечения — это интерактивный процесс. После написания кода его необходимо компилировать и редактировать до тех пор, пока он не будет полностью соответствовать поставленным задачам. Составленное приложение запускается и проверяется на соответствие проектному заданию. Если будут выявлены какие-либо несоответствия, код необходимо будет отредактировать. В средах разработки Flash и Flex Builder предусмотрено несколько способов для публикации, проверки и отладки приложений. Ниже приводятся основные этапы проверки приложения HelloWorld в каждой из упомянутых сред.
Публикация и проверка приложения ActionScript с помощью инструмента разработки Flash
1
Опубликуйте приложение и проверьте его на наличие ошибок компиляции. Для компиляции кода ActionScript и запуска приложения HelloWorld в авторизованном инструменте Flash выберите «Управление» > «Тестировать ролик». 2
Если при проверке приложения в окне «Вывод» появятся сообщения об ошибках или предупреждения, устраните причины этих ошибок в файлах HelloWorld.fla или HelloWorld.as, после чего проверьте приложение снова.
3
При отсутствии ошибок компиляции приложение Hello World появится в окне Flash Player.
После успешного создания простого, но законченного приложения ActionScript 3.0, ориентированного на объект, можно приступить к «Модернизация приложения HelloWorld» на странице 35.
Модернизация приложения HelloWorld
Чтобы сделать приложение более интересным, можно ввести в него подтверждение имени пользователя после сверки с заданным списком имен.
Прежде всего, нужно обновить класс Greeter, расширив его функциональные возможности. Затем следует обновить приложение, чтобы оно могло использовать новые функции.
Обновление файла Greeter.as
1
Откройте файл Greeter.as.
2
Измените содержимое файла следующим образом (новые и измененные строки выделены жирным шрифтом):
36
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
package { public class Greeter { /** * Defines the names that should receive a proper greeting. */ public static var validNames:Array = ["Sammy", "Frank", "Dean"]; /** * Builds a greeting string using the given name. */ public function sayHello(userName:String = ""):String { var greeting:String; if (userName == "") { greeting = "Hello. Please type your user name, and then press the Enter key."; } else if (validName(userName)) { greeting = "Hello, " + userName + "."; } else { greeting = "Sorry " + userName + ", you are not on the list."; } return greeting; } /** * Checks whether a name is in the validNames list. */ public static function validName(inputName:String = ""):Boolean { if (validNames.indexOf(inputName) > -1) { return true; } else { return false; } } } }
Класс Greeter имеет теперь новые свойства: •
В массиве validNames
содержится список разрешенных имен пользователей. При загрузке класса Greeter в массиве устанавливается список из трех имен.
37
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
•
Метод sayHello()
принимает имя пользователя и изменяет приветствие в зависимости от определенных условий. Если имя пользователя userName
задано пустой строкой (
""
), свойство greeting
устанавливается на запрос имени пользователя. Если имя пользователя принято, приветствие выглядит так: "Hello, userName
." И наконец, при невыполнении предыдущих двух условий переменная greeting
устанавливается таким образом: "Sorry userName
, you are not on the list."
(«Извините, [имя пользователя], Вас нет в списке»).
•
Метод validName()
возвращает истинное значение true
, если введенное имя inputName
найдено в массиве validNames
, и возвращает ложное значение false
, если имя не найдено. Инструкция validNames.indexOf(inputName)
сверяет каждую строку массива validNames
со строкой введенного имени inputName
. Метод Array.indexOf()
возвращает указатель позиции первого экземпляра объекта в массиве, то есть значение -1, если объект не найден в массиве.
После этого можно заняться редактированием файлов Flash или Flex, соответствующих данному классу ActionScript.
Модификация приложения с помощью инструмента разработки Flash
1
Откройте файл HelloWorld.fla. 2
Измените сценарий в Кадре 1 так, чтобы пустая строка (
""
) перешла в метод sayHello()
класса Greeter: var myGreeter:Greeter = new Greeter(); mainText.text = myGreeter.sayHello("");
3
Выберите инструмент «Текст» на палитре инструментов, затем создайте два текстовых поля в рабочей области рядом друг с другом и непосредственно под текстовым полем mainText
.
4
В первом новом текстовом поле введите текст User Name:, который будет служить меткой.
5
Выберите другое текстовое поле и установите его тип в инспекторе свойств как InputText. В качестве типа строки выберите Single line (отдельная строка). Введите textIn в качестве имени экземпляра.
6
Щелкните кнопкой мыши первый кадр временной шкалы.
7
На панели «Действия» добавьте следующие строки в конце имеющегося сценария:
mainText.border = true; textIn.border = true; textIn.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); function keyPressed(event:KeyboardEvent):void { if (event.keyCode == Keyboard.ENTER) { mainText.text = myGreeter.sayHello(textIn.text); } }
Новый код добавляет следующие функциональные возможности:
•
Первые две строки просто задают границы для двух текстовых полей.
•
Входное текстовое поле, такое как textIn
, имеет набор событий, которые оно может распределять. Метод addEventListener()
позволяет задать функцию, которая запускается при возникновении события определенного типа. В данном случае этим событием будет нажатие клавиши на клавиатуре.
38
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
•
Настраиваемая функция keyPressed()
проверяет, будет ли нажата именно клавиша Enter. Если требуемая клавиша нажата, метод sayHello()
объекта myGreeter
передает текст из текстового поля textIn
в качестве параметра. Этот метод возвращает строку приветствия, основываясь на переданном значении. Возвращенная строка затем приписывается к свойству text
текстового поля mainText
.
Полный сценарий для Кадра 1 выглядит следующим образом:
var myGreeter:Greeter = new Greeter(); mainText.text = myGreeter.sayHello(""); mainText.border = true; textIn.border = true; textIn.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); function keyPressed(event:KeyboardEvent):void { if (event.keyCode == Keyboard.ENTER) { mainText.text = myGreeter.sayHello(textIn.text); } }
8
Сохраните файл.
9
Для запуска приложения выберите команды «Управление» > «Тестировать ролик». После запуска приложения будет предложено ввести имя пользователя. Если имя принимается программой, появится подтверждающее сообщение «hello».
Рассмотрение последующих примеров
Работа с приложением ActionScript 3.0 «Hello World» позволила приобрести основные знания, необходимые для запуска других демонстрационных сценариев, представленных в настоящем руководстве.
Тестирование примеров кода
При изучении данного руководства рекомендуется самостоятельно тестировать примеры кода, иллюстрирующие различные темы. Тестирование может включать отображение значений переменных в определенных пунктах программы или просмотр содержимого экрана с возможностью интерактивного взаимодействия. Необходимые элементы для тестирования визуального содержимого и интерактивного взаимодействия будут описаны до или внутри примеров кода — для тестирования кода программисту потребуется только создать документ с описанными элементами. Просмотреть значение переменной в определенном пункте программы можно несколькими способами. Одним из этих способов является использование программы отладки. Такие программы (отладчики) встроены в Flex Builder и Flash. Однако для простой проверки будет легче распечатать значения переменной в каком-либо месте, где можно будет просмотреть их.
Следующие шаги помогут создать документ Flash, который можно использовать для тестирования примеров кода и просмотра значений переменной.
Создание документа Flash для тестирования примеров этой главы
1
Создайте новый документ Flash и сохраните его на жесткий диск.
39
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
2
Для отображения тестовых значений в текстовом поле рабочей области активируйте инструмент «Текст» и создайте новое поле динамического текста в рабочей области. Наиболее пригодным для этих целей будет широкое и высокое текстовое поле с включенной рамкой и многострочным типом линии. В инспекторе свойств присвойте текстовому полю имя экземпляра (например, «outputText»). Чтобы записать значения в текстовое поле, необходимо добавить код, вызывающий метод appendText()
кода примера (описание приведено ниже).
3
Альтернативно можно добавить к примеру кода (описание приведено ниже) обращение к функции trace()
для просмотра результатов примера.
4
Для тестирования примера скопируйте код на панель «Действия»; при необходимости добавьте обращение к функции trace()
или добавьте значение в текстовое поле, используя его метод appendText()
.
5
Для создания SWF-файла и просмотра результатов выберите в главном меню команды «Управление» > «Тестировать ролик».
Поскольку эта методика предназначена для просмотра значений переменных, существует два простых способа сделать это во время тестирования примеров: запишите значения в экземпляр текстового поля в рабочей области или воспользуйтесь функцией trace()
для распечатки значений на панели «Вывод».
•
Функция trace()
: функция trace()
в ActionScript записывает значения любых передаваемых ей параметров (переменных или литеральных выражений) на панель «Вывод». Многие из примеров кода данного руководства уже включают в себя вызов функции trace()
, поэтому для этих примеров достаточно всего лишь скопировать код в документ и протестировать проект. Если же требуется использовать функцию trace()
для проверки значения переменной в примере кода, который этой функции еще не включает, необходимо добавить в код вызов trace()
, передав переменную как параметр. Например, если вам встретился следующий код:
var albumName:String = "Three for the money";
Для тестирования результата примера кода можно скопировать код на панель «Действия», а затем добавить вызов функции trace()
, например:
var albumName:String = "Three for the money"; trace("albumName =", albumName);
При запуске программы будет распечатана следующая строка:
albumName = Three for the money
Каждый вызов функции trace()
может иметь несколько параметров, причем все они соединяются в одну строку при распечатке. Если в конце каждого обращения к функции trace()
добавить разрыв строки, результаты обращений к функции trace()
будут распечатаны на отдельных строках.
•
Текстовое поле в рабочей области: вместо функции trace()
можно добавить поле динамического текста в рабочую область (используя инструмент «Текст») и выписать значения в это текстовое поле для просмотра результатов примера кода. Метод appendText()
класса TextField можно использовать для добавления значения строки String в конце содержимого текстовых полей. Для доступа к текстовому полю с помощью ActionScript необходимо задать ему имя экземпляра в инспекторе свойств. Например, если текстовое поле имеет имя экземпляра outputText
, для проверки значения переменной albumName
можно использовать следующий код.
var albumName:String = "Three for the money"; outputText.appendText("albumName = "); outputText.appendText(albumName);
Код запишет следующий текст в текстовое поле с именем outputText
:
albumName = Three for the money
40
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Начало работы с языком ActionScript
Как показано в этом примере, метод appendText()
добавит текст к той же строке, в которой находилось предыдущее содержимое. Таким образом, используя множественные обращения к appendText()
, можно добавить несколько значений к одной и той же строке. Чтобы перевести текст на новую строку, необходимо добавить символ разделителя строк (
"\n"
):
outputText.appendText("\n"); // adds a line break to the text field
В отличие от функции trace()
, метод appendText()
может принять только одно значение в качестве параметра. Это значение должно быть строкой (экземпляр String или строковый литерал). Для распечатки значения нестроковой переменной необходимо сначала конвертировать его в значение строки. Легче всего сделать это, вызвав метод объекта toString()
:
var albumYear:int = 1999; outputText.appendText("albumYear = "); outputText.appendText(albumYear.toString());
Работа с примерами, приведенными в конце главы
Эта глава, как и большинство других глав данного руководства, содержит в конце большое количество примеров, которые связывают воедино основные концепции, которые были здесь рассмотрены. Тем не менее, эти примеры, в отличие от приложения Hello World, не содержат пошаговых инструкций. Соответствующий код ActionScript 3.0 для каждого примера будет рассмотрен и обсужден, однако инструкции по запуску и работе в специальных средах разработки не приводятся. Тем не менее, материалы примеров, поставляемые с настоящим руководством, включают все необходимые файлы, позволяющие легко составить и запустить учебные приложения в выбранной среде разработки.
41
Глава 4. Язык ActionScript и его синтаксис
ActionScript 3.0 включает как язык ядра ActionScript, так и прикладной программный интерфейс Adobe Flash Player. Базовый язык — это часть кода ActionScript, которая определяет синтаксис языка, а также типы данных верхнего уровня. ActionScript 3.0 обеспечивает программный доступ к проигрывателю Flash Player.
В этой главе представлено краткое введение в язык ядра ActionScript и его синтаксис. Информация этой главы дает общее представление о том, как работать с типами данных и переменными, как использовать правильный синтаксис, как управлять потоком данных в программе.
Обзор языка
В основу языка ActionScript 3.0 положены объекты, они являются его главным конструктивным материалом. Каждая объявленная переменная, каждая написанная функция, каждый созданный экземпляр класса являются объектами. Программу на ActionScript 3.0 можно рассматривать как группу объектов, выполняющих задачи, реагирующих на события и взаимодействующих друг с другом. Программисты, знакомые с объектно-ориентированным программированием в Java или C++, могут воспринимать объекты как модули, включающие два типа: данных, хранимые в соответствующих переменных или свойствах, а также поведение, реализуемое с помощью методов. ActionScript 3.0 определяет объекты подобным образом, но немного по-другому. В ActionScript 3.0 объекты представляют собой просто наборы свойств. Эти свойства выступают в качестве контейнеров, которые могут содержать не только данные, но также функции или другие объекты. Если функция связана с объектом таким образом, она называется методом. Хотя определение ActionScript 3.0 и может показаться немного странным для имеющего опыт программирования на Java или C++, на практике определение типов объектов с помощью классов ActionScript 3.0 сходно со способом, которым классы определяются в Java или C++. Различие между двумя определениями объектов важно, когда обсуждается объектная модель ActionScript и другие расширенные возможности, но в большинстве других ситуаций термин свойства означает переменные, являющиеся членами класса, как альтернативу методам. В справочнике по языку ActionScript 3.0 и компонентам, например, термин свойства используется для обозначения переменных или свойств getter-setter. Термин методы здесь используется для обозначения функций, являющихся частью класса.
Единственным небольшим различием между классами в ActionScript и классами в Java или С++ является то, что в ActionScript-классы это не просто абстрактные сущности. В ActionScript классы представляются объектами классов, хранящими свойства и методы этого класса. Это позволяет реализовывать методики, которые могут показаться незнакомыми программистам на Java и C++, например, включение инструкций или исполняемого программного кода в верхний уровень класса или пакета.
42
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Другим различием между классами ActionScript и классами в Java или C++ является то, что каждый класс ActionScript обладает так называемым объектомпрототипа. В предыдущих версиях ActionScript объекты прототипов, связанные вместе в цепочки прототипов, совместно служили в качестве основания всей иерархии наследования класса. Однако в ActionScript 3.0 объекты прототипов играют лишь малую роль в системе наследования. Объект прототипа также может быть полезен, но как альтернатива статическим свойствам и методам, если требуется обеспечить совместное использование свойства и его значений всеми экземплярами класса.
В прошлом искушенные программисты ActionScript могли напрямую управлять цепочкой прототипов с помощью специальных встроенных элементов языка. Теперь, когда в языке предлагается более зрелая реализация интерфейса программирования, основанного на классах, многие из этих специальных элементов языка, таких как __proto__
и __resolve,
больше не являются частью языка. Кроме того, оптимизация внутреннего механизма наследования, обеспечивающая значительный прирост производительности в Flash Player и Adobe AIR, предотвращает прямой доступ к механизму наследования. Объекты и классы
В ActionScript 3.0 каждый объект определяется классом. Класс можно рассматривать как шаблон или проект типа объекта. Определения класса могут включать переменные и константы, которые содержат значения данных и методов, являющихся функциями, содержащими поведение, связанное с этим классом. Значения, хранимые в свойствах, могут быть примитивными значениями или другими объектами. Примитивные значения — это числа, строки или логические значения. ActionScript содержит ряд встроенных классов, являющихся частью языка ядра. Некоторые из этих встроенных классов, например Number, Boolean и String, отражают примитивные значения, доступные в ActionScript. Другие же, такие как классы Array, Math и XML, определяют более сложные объекты.
Все классы, независимо от того, являются ли они встроенными или определяемыми пользователем, выводятся из класса Object. Программистам, имеющим опыт работы с предыдущей версией ActionScript, важно обратить внимание на то, что тип данных Object больше не является типом данных по умолчанию, даже несмотря на то что все другие классы являются его производными. В ActionScript 2.0 следующие две строки программного кода были эквивалентны, поскольку отсутствие аннотации типа означало, что переменная будет иметь тип Object.
var someObj:Object; var someObj;
В ActionScript 3.0 вводится концепция переменных без объявления типа, которые можно назначать следующими двумя способами.
var someObj:*; var someObj;
Переменная без объявления типа отличается от переменной с типом Object. Основным отличием является то, что переменные без объявления типа могут содержать специальное значение undefined
, в то время как переменные с типом Object не могут содержать такое значение. Можно определить свои собственные классы, используя ключевое слово class
. Свойства класса можно объявить тремя способами: константы могут быть определены с помощью ключевого слова const
, переменные определяются с помощью ключевого слова var
, а свойства getter и setter определяются с использованием атрибутов get
и set
в объявлении метода. Методы можно объявлять с помощью ключевого слова function
. 43
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Экземпляр класса создается с помощью оператора new
. В следующем примере создается экземпляр класса Date с названием myBirthday
.
var myBirthday:Date = new Date();
Пакеты и пространства имен
Пакеты и пространства имен являются взаимосвязанными концепциями. Пакеты позволяют связывать определения классов вместе таким способом, что облегчается совместное использование кода и снижается вероятность конфликтов имен. Пространства имен позволяют управлять видимостью идентификаторов, например именами свойств и методов, их можно применять к программному коду независимо от того, внутри или вне пакета он находится. Пакеты позволяют организовать файлы классов, а пространства имен позволяют управлять видимостью отдельных свойств и методов. Пакеты
Пакеты в ActionScript 3.0 реализуются с помощью пространств имен, но эти два понятия не являются синонимами. При объявлении пакета явно создается специальный тип пространства имен, который гарантированно будет известен во время компиляции. Пространства имен, когда создаются явным образом, не обязательно известны во время компиляции. В следующем примере для создания простого пакета, содержащего один класс, используется директива package
. package samples { public class SampleCode { public var sampleGreeting:String; public function sampleFunction() { trace(sampleGreeting + " from sampleFunction()"); } } }
Именем класса в данном случае является SampleCode. Поскольку класс находится внутри пакета примеров, компилятор автоматически уточняет имя класса во время компиляции, воссоздавая полное имя: samples.SampleCode. Компилятор также уточняет имена любых свойств или методов, так что имена sampleGreeting
и sampleFunction()
становятся соответственно samples.SampleCode.sampleGreeting
и samples.SampleCode.sampleFunction()
.
Многие разработчики, особенно те, кто программирует на Java, могут захотеть размещать классы только на верхнем уровне пакетов. В тоже время ActionScript 3.0 поддерживает на верхнем уровне пакета не только классы, но и переменные, функции и даже инструкции. Одним из современных способов использования этой возможности является определение пространства имен на верхнем уровне пакета, так чтобы оно было доступно для всех классов этого пакета. Однако следует обратить внимание, что на верхнем уровне пакета разрешены только два спецификатора доступа, public
и internal
. В отличии от Java, где можно объявлять вложенные классы частными, в ActionScript 3.0 не поддерживаются ни вложенные, ни частные классы.
44
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Во многом другом, однако, пакеты ActionScript 3.0 сходны с пакетами в языке программирования Java. Как видно из предыдущего примера, полностью уточненные ссылки на пакет передаются с помощью оператора точки (
.
), как это делается в Java. Можно использовать пакеты для организации собственного программного кода в интуитивно понятную иерархическую структуру, с которой смогут работать другие программисты. Это упрощает совместную работу с программными кодами, позволяя создавать собственные пакеты для использования другими разработчиками, а также применять пакеты, созданные другими, в собственном программном коде. Использование пакетов также помогает соблюсти уникальность имен применяемых идентификаторов и предотвратить конфликты с именами других идентификаторов. Действительно, кто-то наверное скажет, что это основное преимущество использования пакетов. Например, два программиста, которым необходимо совместно использовать между собой свои программные коды, могут каждый создать класс с названием SampleCode. Без пакетов при этом возникнет конфликт имен, единственным решением которого будет переименование одного из классов. Однако благодаря использованию пакетов конфликт имен легко предотвращается, поскольку один, а лучше оба класса можно поместить в пакеты с уникальными именами.
Также в имена пакетов можно включить встроенные точки, чтобы создать вложенные пакеты. Это позволяет создавать иерархическую структуру пакетов. Хорошим примером служит пакет flash.xml, предоставляемый в рамках ActionScript 3.0. Пакет flash.xml вложен в пакет flash. Пакет flash.xml содержит старую программу синтаксического анализа XML, которая использовалась в предыдущих версиях ActionScript. Одной из причин, почему эта программа теперь находится в пакете flash.xml, является то, что имя старого класса XML конфликтовало с именем нового класса XML, в котором реализованы функции, соответствующие спецификации XML для ECMAScript (E4X), доступные в ActionScript 3.0. Хотя перемещение старого класса XML в пакет будет хорошим начальным шагом, большинство пользователей старых классов XML выполнят импорт пакета flash.xml, который создаст тот же самый конфликт имен, если не будет использоваться полностью уточненное имя старого класса XML (flash.xml.XML). Чтобы избежать этой ситуации, старый класс XML теперь называется XMLDocument, как показано в следующем примере. package flash.xml { class XMLDocument {} class XMLNode {} class XMLSocket {} }
Язык ActionScript 3.0 главным образом организован внутри пакета flash. Например, пакет flash.display содержит прикладной программный интерфейс списка отображения, а пакет flash.events содержит новую модель событий.
Создание пакетов
ActionScript 3.0 обеспечивает значительную гибкость в способах организации пакетов, классов и исходных файлов. В предыдущих версиях ActionScript разрешалось размещать только один класс в одном исходном файле, а также требовалось совпадение имен файла и класса. ActionScript 3.0 позволяет включать несколько классов в один исходный файл, но только один класс в каждом файле может быть сделан доступным для программного кода, внешнего по отношению к файлу. Говоря другими словами, только один класс в каждом файле может быть объявлен в декларации пакета. Необходимо объявлять любые дополнительные классы вне определения пакета, что сделает такие классы невидимыми для программного кода вне этого исходного файла. Имя класса, объявляемого в определении пакета, должно соответствовать имени исходного файла.
45
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
ActionScript 3.0 обеспечивает более гибкие возможности при объявлении пакетов. В предыдущих версиях ActionScript пакеты всего лишь представляли собой каталоги, в которые помещались исходные файлы, и эти пакеты объявлялись не с помощью инструкции package
, а просто имя пакета включалось как часть полного уточненного имени класса в определение класса. Хотя пакеты по-прежнему представляют собой каталоги в ActionScript 3.0, они могут содержать не только классы. В ActionScript 3.0 для объявления пакета используется инструкция package
, что означает, что также можно объявлять переменные, функции и пространства имен на верхнем уровне пакета. На верхнем уровне пакета также можно добавлять выполняемые инструкции. Если на верхнем уровне пакета объявляются переменные, функции или пространства имен, то единственными атрибутами, доступными на этом уровне, являются public
и internal
. Только одно объявление пакета в файле может использовать атрибут public
, независимо от того, объявляется ли при этом класс, переменная, функция или пространство имен. Пакеты особенно полезны при упорядочивании программных кодов, а также для предотвращения конфликтов имен. Но не нужно путать концепцию пакетов с несвязанной с ней концепцией наследования классов. Два класса, находящиеся в одном и том же пакете, будут иметь общее пространство имен, но совсем не обязательно, что они связаны между собой каким-то иным образом. Сходным образом вложенный пакет может не иметь семантических связей со своим родительским пакетом.
Импорт пакетов
Если требуется использовать класс, находящийся внутри пакета, необходимо выполнить импорт либо этого пакета, либо определенного класса. Это отличается от технологии, используемой в ActionScript 2.0, где импорт классов был необязателен. Например, рассмотрите пример класса SampleCode, приведенный ранее в этой главе. Если класс находится в пакете с именем samples, необходимо использовать одну из следующих инструкций import, прежде чем использовать класс SampleCode.
import samples.*;
или
import samples.SampleCode;
В целом инструкции import
должны быть максимально конкретизированы. Если планируется использовать только класс SampleCode из пакета samples, необходимо импортировать только класс SampleCode, но не весь пакет, к которому он принадлежит. Импорт всего пакета может привести к неожиданным конфликтам имен.
Необходимо также размещать исходный код, определяющий пакет или класс, внутри подкаталога классов. Подкаталог классов — это задаваемый пользователем список путей к локальным каталогам, определяющий, где компилятор будет искать импортированные пакеты и классы. Подкаталог классов иногда называют путем построения или исходным путем. После того как класс и пакет правильно импортированы, можно использовать либо полностью уточненное имя класса (samples.SampleCode), либо просто само имя класса (SampleCode).
Полностью уточненные имена очень полезны в тех случаях, когда одинаковые имена классов, методов или свойств приводят к неоднозначностям в программных кодах, но может усложнится управление, если использовать такие имена для всех идентификаторов. Например, использование полностью уточненных имен приводит к слишком подробному коду при создании экземпляра класса SampleCode.
var mySample:samples.SampleCode = new samples.SampleCode();
46
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
По мере увеличения уровней вложенности пакетов читаемость такого программного кода снижается. Поэтому в тех ситуациях, когда есть уверенность, что неоднозначность идентификаторов может вызвать проблемы, можно упрощать программный код, используя простые идентификаторы. Например, для создания нового экземпляра класса SampleCode требуется гораздо меньше информации, если использовать только идентификатор класса.
var mySample:SampleCode = new SampleCode();
Если попытаться использовать имена идентификаторов без предварительного импорта соответствующего пакета или класса, компилятор не сможет найти определения классов. С другой стороны, если импортировать пакет или класс, то любая попытка определить имя, конфликтующее с именем импортированного объекта, приведет к возникновению ошибки.
Если создается пакет, спецификатор доступа по умолчанию для всех членов этого пакета установлен как internal
, и это означает, что по умолчанию члены пакета видны только другим членам этого пакета. Если требуется, чтобы класс был доступен для программного кода вне пакета, необходимо объявить этот класс как public
. Например, в следующем пакете содержатся два класса, SampleCode и CodeFormatter. // SampleCode.as file package samples { public class SampleCode {} } // CodeFormatter.as file package samples { class CodeFormatter {} }
Класс SampleCode виден вне пакета, потому что он объявлен как класс public
. Класс CodeFormatter, в то же время, видим только внутри самого пакета samples. При попытке обращения к классу CodeFormatter извне пакета samples появится сообщение об ошибке, как показано в следующем примере.
import samples.SampleCode; import samples.CodeFormatter; var mySample:SampleCode = new SampleCode(); // okay, public class var myFormatter:CodeFormatter = new CodeFormatter(); // error
Если требуется, чтобы оба класса были доступны за пределами пакета, необходимо объявить оба этих класса как public
. Нельзя применить атрибут public
при объявлении пакета. Полностью уточненные имена полезны при разрешении конфликтов имен, которые могут произойти при использовании пакетов. Такие сценарии могут возникать, если импортируются два пакета, определяющие классы с одинаковым идентификатором. Например, рассмотрим следующий пакет, в котором также имеется класс с названием SampleCode.
package langref.samples { public class SampleCode {} }
Если импортировать оба класса, как показано далее, возникнет конфликт имен при обращении к классу SampleCode.
import samples.SampleCode; import langref.samples.SampleCode; var mySample:SampleCode = new SampleCode(); // name conflict
47
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Компилятор не сможет распознать, какой класс SampleCode использовать. Чтобы разрешить этот конфликт, необходимо использовать полностью уточненное имя.
var sample1:samples.SampleCode = new samples.SampleCode(); var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
Примечание. Программисты со стажем работы на C++ часто путают инструкцию import
с #include
. Директива #include
необходима в C++, поскольку компиляторы этого языка одновременно обрабатывают только один файл и не будут заглядывать в другие файлы в поисках определений классов, пока явно не включен файл заголовка. В ActionScript 3.0 также есть директива include
, но она не предназначена для импорта классов и пакетов. Для импорта классов и пакетов в ActionScript 3.0 необходимо использовать инструкцию import
и помещать исходный файл, содержащий пакет, в подкаталог классов.
Пространства имен
Пространства имен позволяют управлять доступностью создаваемых свойств и методов. Можно рассматривать спецификаторы управления доступом public
, private
, protected
и internal
как встроенные пространства имен. Если эти предварительно определенные спецификаторы управления доступом не соответствуют имеющимся требованиям, можно создать собственные пространства имен. Тем, кто имеет представление о пространствах имен XML, большая часть обсуждаемой здесь информации покажется знакомой, хотя синтаксис и подробные сведения реализации пространств имен в ActionScript слегка отличаются от используемых в XML. Но даже если раньше работать с пространствами имен не приходилось, эта концепция достаточно понятна, правда в ее реализации используется специфическая терминология, которую нужно освоить. Чтобы разобраться, как работают пространства имен, полезно знать, что имя свойства или метода всегда состоит из двух частей: идентификатора и пространства имен. Идентификатор — это та часть, которая обычно воспринимается как имя. Например, идентификаторами в следующем классе являются sampleGreeting
и sampleFunction()
.
class SampleCode { var sampleGreeting:String; function sampleFunction () { trace(sampleGreeting + " from sampleFunction()"); } }
В тех случаях, когда определения не предваряются атрибутом пространства имен, их имена по умолчанию уточняются как относящиеся к пространству имен internal
, и это означает, что они видимы для вызова только в рамках данного пакета. Если для компилятора задан строгий режим работы, он создает предупреждение о применении пространства имен internal
к любому идентификатору без атрибута пространства имен. Для обеспечения широкого доступа к идентификатору необходимо специально предварять его имя атрибутом public
. В предыдущем примере программного кода для обоих классов sampleGreeting
и sampleFunction()
в качестве значения пространства имен указано internal
.
При использовании пространств имен необходимо выполнить три основных шага. Прежде всего необходимо определить пространство имен, используя ключевое слово namespace
. Например, в следующем программном коде определяется пространство имен version1
. namespace version1;
Во-вторых, необходимо применить пространство имен, используя его вместо спецификатора контроля доступа при объявлении свойства или метода. В следующем примере функция с именем myFunction()
размещается в пространстве имен version1
.
48
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
version1 function myFunction() {}
В-третьих, как только пространство имен будет применено, к нему можно адресоваться с помощью директивы use
или уточняя имя идентификатора указанием пространства имен. В следующем примере функция myFunction()
вызывается с использованием директивы use
.
use namespace version1; myFunction();
Для вызова функции myFunction()
можно также использовать уточненное имя, как показано в следующем примере.
version1::myFunction();
Определение пространств имен
Пространства имен содержат одно значение, универсальный идентификатор ресурса (URI), который иногда называется именем пространства имен. Идентификатор URI позволяет обеспечить уникальность определения пространства имен. Пространство имен создается путем объявления определения пространства имен одним из следующих способов. Можно либо определить пространство имен путем явного указания URI, как это делалось бы для пространства имен XML, либо можно пропустить URI. В следующем примере показано, как можно определить пространство имен с помощью URI.
namespace flash_proxy = "http://www.adobe.com/flash/proxy";
Идентификатор URI выступает в качестве уникальной строки идентификации пространства имен. Если идентификатор URI пропущен, как показано в следующем примере, компилятор создаст уникальную внутреннюю строку идентификации вместо этого URI. Доступ пользователя к этой внутренней строке идентификации невозможен.
namespace flash_proxy;
Как только пространство имен определено, с использованием URI или без его использования, это пространство имен не может быть переопределено в той же области действия. Попытка определить пространство имен, которое уже было определено ранее в этой области действия, приведет к ошибке компилятора. Если пространство имен определяется в пакете или классе, это пространство имен может быть невидимо для программного кода за пределами этого пакета или класса до тех пор, пока не будет использован соответствующий спецификатор контроля доступа. Например, в следующем программном коде показано пространство имен flash_proxy
, определенное в пакете flash.utils. В следующем примере отсутствие спецификатора контроля доступа означает, что пространство имен flash_proxy
будет видимо только программному коду в самом пакете flash.utils и будет недоступно любому программному коду вне пакета.
package flash.utils { namespace flash_proxy; }
В следующем программном коде атрибут public
используется для открытия доступа к пространству имени flash_proxy
извне этого пакета.
package flash.utils { public namespace flash_proxy; }
49
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Применение пространств имен
Применение пространства имен означает размещение определения в пространство имен. В число определений, которые можно помещать в пространства имен, входят функции, переменные и постоянные (нельзя поместить класс в произвольное пространство имен). Например, рассмотрим функцию, объявленную с использованием пространства имен для контроля доступа public
. Использование атрибута public
в определении функции вызывает ее размещение в пространстве имен public, что делает эту функцию доступной для всех программных кодов. Как только пространство имен задано, можно использовать его тем же способом, что и атрибут public
, а определение будет доступно программному коду, из которого можно обращаться к произвольно заданным пространствам имен. Например, если определяется пространство имен example1
, можно добавить метод с названием myFunction()
, используя в качестве атрибута example1
, как показано в следующем примере.
namespace example1; class someClass { example1 myFunction() {} }
Объявление метода myFunction()
с использованием пространства имен example1
в качестве атрибута означает, что этот метод принадлежит пространству имен example1
. При применении пространств имен необходимо учитывать следующие правила.
•
Для каждого объявления можно применять только одно пространство имен. •
Невозможно применить атрибут пространства имен более чем к одному определению одновременно. Говоря другими словами, если потребуется применить пространство имен к десяти различным функциям, необходимо будет добавить это пространство имен в качестве атрибута к определению каждой из десяти функций. •
Если применяется пространство имен, нельзя также указывать спецификатор контроля доступа, поскольку пространства имен и спецификаторы контроля доступа взаимоисключают друг друга. То есть нельзя объявить функцию или свойство с атрибутом public
, private
, protected
или internal
в дополнение к применению пространства имен.
Привязка пространств имен
Нет необходимости явно выполнять привязку к пространствам имен, если используется метод или свойство, объявленные с каким-либо пространством имен для контроля доступа, например атрибутами public
, private
, protected
и internal
. Доступ к этим специальным пространствам имен управляется контекстом. Например, определения, помещенные в пространство имен private
, автоматически доступны для программных кодов в рамках данного класса. Однако для самостоятельно определенных пространств имен такой контекстной чувствительности не существует. Чтобы использовать метод или свойство, помещенное в произвольное пространство имен, необходимо выполнить привязку к этому пространству имен.
Привязку пространства имен можно выполнить с помощью директивы use namespace
или можно уточнить имя с помощью пространства имен, используя в качестве уточняющего имя знака пунктуации (
::
). Привязка пространства имен с помощью директивы use namespace
открывает пространство имен, так что его можно применять к любому неуточненному идентификатору. Например, если определено пространство имен example1
, можно обращаться к именам в этом пространстве, используя директиву use namespace example1
.
use namespace example1; myFunction();
50
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Одновременно может быть открыто сразу несколько пространств имен. Как только пространство имен открыто с помощью директивы use namespace
, оно становится открытым для всего блока программного кода, в котором оно открыто. Не существует способов явным образом закрыть пространство имен.
Открытие нескольких пространств имен увеличивает вероятность возникновения конфликтов имен. Если предпочтительнее не открывать пространство имен, можно избежать директивы use namespace
, просто уточняя имя метода или свойства с помощью пространства имен и уточняющего имя знака пунктуации. Например, в следующем программном коде показано, как можно уточнить имя myFunction()
, используя пространство имен example1
.
example1::myFunction();
Использование пространств имен
Можно найти конкретный пример пространства имен, используемого для предотвращения конфликтов имен в классе flash.utils.Proxy, который входит в состав ActionScript 3.0. Класс Proxy, заменивший класс Object.__resolve
, который использовался в ActionScript 2.0, позволяет перехватывать обращения к неопределенным свойствам или методам, перед тем как произойдет ошибка. Все методы класса Proxy находятся в пространстве имен flash_proxy
, чтобы предотвратить конфликты пространства имен.
Чтобы лучше понять, как используется пространство имен flash_proxy
, необходимо разобраться с порядком использования класса Proxy. Функциональные возможности класса Proxy доступны только для классов, наследуемых из него. То есть если потребуется использовать методы класса Proxy к объекту, определение класса объекта должно расширять класс Proxy. Например, если требуется перехватить попытки вызова неопределенных методов, следует расширить класс Proxy, а затем переписать метод callProperty()
в классе Proxy. Необходимо помнить, что применение пространств имен обычно включает три этапа: определение, применение и привязку. Поскольку методы класса Proxy никогда не вызываются явным образом, то пространство имен flash_proxy
только определяется и применяется, но никогда не привязывается. ActionScript 3.0 определяет пространство имен flash_proxy
и применяет его в классе Proxy. Затем программному коду необходимо только применить пространство имен flash_proxy
к классам, расширяющим класс Proxy. Пространство имен flash_proxy
определяется в пакете flash.utils способом, аналогичным следующему.
package flash.utils { public namespace flash_proxy; }
Пространство имен применяется к методам класса Proxy, как показано в следующей выборке из класса Proxy.
public class Proxy { flash_proxy function callProperty(name:*, ... rest):* flash_proxy function deleteProperty(name:*):Boolean ... }
Как показано в следующем программном коде, необходимо вначале импортировать как класс Proxy, так и пространство имен flash_proxy
. Затем следует объявить свой класс, расширяющий класс Proxy (необходимо также добавить атрибут dynamic
, если предполагается компиляция в строгом режиме). Когда метод callProperty()
будет перезаписан, необходимо использовать пространство имен flash_proxy
.
51
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
package { import flash.utils.Proxy; import flash.utils.flash_proxy; dynamic class MyProxy extends Proxy { flash_proxy override function callProperty(name:*, ...rest):* { trace("method call intercepted: " + name); } } }
Если создается экземпляр класса MyProxy и вызывается неопределенный метод, например метод testing()
, см. следующий пример, то объект Proxy перехватывает вызов метода и выполняет инструкции, находящиеся в перезаписанном методе callProperty()
(в данном случае простую инструкцию trace()
).
var mySample:MyProxy = new MyProxy(); mySample.testing(); // method call intercepted: testing
Расположение методов класса Proxy в пространстве имен flash_proxy
обеспечивает два преимущества. Во-
первых, отдельное пространство имен уменьшает беспорядок интерфейса общего доступа для любого класса, расширяющего класс Proxy. (В классе Proxy имеется около двенадцати методов, которые можно перезаписать, все они не предназначены для прямого вызова. Размещение всех их в пространстве имен public может привести к сбоям.) Во-вторых, использование пространства имен flash_proxy
предотвращает конфликты имен, в случае если подкласс Proxy содержит методы экземпляров с именами, совпадающими с какими-либо именами методов в классе Proxy. Например, может потребоваться назвать один из создаваемых методов callProperty()
. Показанный далее программный код допустим, поскольку созданная версия метода callProperty()
находится в другом пространстве имен.
dynamic class MyProxy extends Proxy { public function callProperty() {} flash_proxy override function callProperty(name:*, ...rest):* { trace("method call intercepted: " + name); } }
Пространства имен также могут быть полезны, если требуется обеспечить доступ к методам или свойствам таким способом, который нельзя организовать четырьмя спецификаторами контроля доступа (
public
, private
, internal
и protected
). Например, может получиться, что несколько служебных методов распределены между несколькими пакетами. Требуется, чтобы эти методы были доступны для всех этих пакетов, но в то же время методы должны быть закрыты для общего доступа. Для решения этой задачи можно создать несколько пространств имен и использовать их в качестве собственных специальных спецификаторов контроля доступа. В следующем примере определенное пользователем пространство имен используется для группирования вместе двух функций, находящихся в разных пакетах. Группируя их в одном пространстве имен, можно сделать обе функции видимыми для класса и пакета, используя одну инструкцию use namespace
.
52
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
В этом примере, чтобы продемонстрировать данную технологию, используется четыре файла. Все эти файлы должны находиться в подкаталоге классов. Первый файл, myInternal.as, используется для определения пространства имен myInternal
. Поскольку этот файл находится в пакете с именем example, необходимо поместить файл в папку с именем example. Пространство имен помечено как public
, поэтому его можно импортировать в другие пакеты. // myInternal.as in folder example package example { public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples"; }
Второй и третий файлы, Utility.as и Helper.as, определяют классы, которые содержат методы, доступные для других пакетов. Класс Utility находится в пакете example.alpha, что означает, что файл должен быть помещен в папку alpha, вложенную в папку example. Класс Helper находится в пакете example.beta, что означает, что файл должен быть помещен в папку beta, вложенную в папку example. Оба этих пакета, example.alpha и example.beta, должны импортировать пространство имен, прежде чем использовать его.
// Utility.as in the example/alpha folder package example.alpha { import example.myInternal; public class Utility { private static var _taskCounter:int = 0; public static function someTask() { _taskCounter++; } myInternal static function get taskCounter():int { return _taskCounter; } } } 53
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
// Helper.as in the example/beta folder package example.beta { import example.myInternal; public class Helper { private static var _timeStamp:Date; public static function someTask() { _timeStamp = new Date(); } myInternal static function get lastCalled():Date { return _timeStamp; } } }
Четвертый файл, NamespaceUseCase.as, является основным классом приложения и должен располагаться на одном уровне с папкой example. В Adobe Flash CS4 Professional этот класс будет использоваться в качестве класса документа для FLA. Класс NamespaceUseCase также импортирует пространство имен myInternal
и использует его для вызова двух статических методов, которые находятся в других пакетах. Статические методы в этом примере использованы исключительно для упрощения программного кода. Оба метода, статический и создающий экземпляр, могут размещаться в пространстве имен myInternal
.
// NamespaceUseCase.as package { import flash.display.MovieClip; import example.myInternal; // import namespace import example.alpha.Utility;// import Utility class import example.beta.Helper;// import Helper class public class NamespaceUseCase extends MovieClip { public function NamespaceUseCase() { use namespace myInternal; Utility.someTask(); Utility.someTask(); trace(Utility.taskCounter); // 2 Helper.someTask(); trace(Helper.lastCalled); // [time someTask() was last called] } } }
54
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Переменные
Переменные позволяют сохранять значения, используемые в программе. Чтобы объявить переменную, необходимо использовать инструкцию var
с именем переменной. В ActionScript 2.0 использование инструкции var
требуется, только если используются аннотации типов. В ActionScript 3.0 использование инструкции var
требуется всегда. Например, в следующей строке ActionScript объявляется переменная с именем i
: var i;
Если пропустить инструкцию var
при объявлении переменной, будет выдана ошибка компилятора в строгом режиме и ошибка при выполнении в стандартном режиме. Например, в следующей строке программного кода будет возникать ошибка, если переменная i
ранее не была определена.
i; // error if i was not previously defined
Для связи переменной с типом данных это необходимо при объявлении переменной. Объявление переменной без указания ее типа разрешено, но при этом будет создаваться предупреждение в строгом режиме компилятора. Тип переменной назначается добавлением к имени переменной двоеточия (:) с последующим указанием типа этой переменной. Например, в следующем программном коде объявляется переменная i
, которая имеет тип int.
var i:int;
Значение переменной можно задать, используя оператор присваивания (
=
). Например, в следующем коде объявляется переменная i
и ей назначается значение 20.
var i:int; i = 20;
Возможно, покажется более удобным назначать значение переменной одновременно с ее объявлением, как показано в следующем примере.
var i:int = 20;
Технология назначения значения переменной во время ее объявления широко используется не только при назначении примитивных значений, таких как целочисленные значения и строки, но также при создании массивов или создании экземпляров классов. В следующем примере показано, как в одной строчке программного кода создается массив и ему присваивается значение.
var numArray:Array = ["zero", "one", "two"];
Можно создать экземпляр класса с помощью оператора new
. В следующем примере создается экземпляр с именем CustomClass
и выполняется привязка вновь созданного экземпляра класса переменной с именем customItem
.
var customItem:CustomClass = new CustomClass();
Если объявляется больше одной переменной, можно объявить их все в одной строке кода, используя оператор запятой (
,
) для разделения переменных. Например, в следующем программном коде объявляется три переменных в одной строке кода.
var a:int, b:int, c:int;
Также можно назначить значения каждой из переменных в одной строке кода. Например, в следующем программном коде объявляются три переменные (
a
, b
и c
) и каждой из них назначается значение.
var a:int = 10, b:int = 20, c:int = 30;
55
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Хотя можно использовать оператор запятой для группирования объявления переменных в одной инструкции, это может привести к снижению наглядности программного кода.
Знакомство с областью действия переменной
Областью действия переменной является область программного кода, где данная переменная доступна для лексических ссылок. Переменная global объявляется для всех областей программного кода, а переменная local — только для какой-то его части. В ActionScript 3.0 переменным всегда назначается область действия функции или класса, в которой они объявлены. Глобальная переменная — это переменная, определяемая вне определения какой-либо функции или класса. Например, в следующем программном коде глобальная переменная strGlobal
создается путем обновления ее вне какой-либо функции. В этом примере показано, что глобальная переменная доступна как вне, так и внутри определения функции. var strGlobal:String = "Global"; function scopeTest() { trace(strGlobal); // Global } scopeTest(); trace(strGlobal); // Global
Локальная переменная объявляется путем объявления переменной внутри функции. Наименьшей областью кода, для которой можно определить локальную переменную, является определение функции. Локальная переменная, объявленная внутри функции, будет существовать только в этой функции. Например, если объявляется переменная с именем str2
в функции с именем localScope()
, то эта переменная не будет доступна вне данной функции.
function localScope() { var strLocal:String = "local"; } localScope(); trace(strLocal); // error because strLocal is not defined globally
Если используемое для локальной переменной имя уже объявлено для глобальной переменной, локальное определение скрывает (или затеняет) глобальное определение, пока локальная переменная находится в области действия. А глобальная переменная будет по-прежнему существовать вне этой функции. Например, в следующем программном коде создается глобальная строковая переменная с именем str1
, а затем создается локальная переменная с тем же именем в функции scopeTest()
. Инструкция trace
в функции выводит локальное значение этой переменной, а инструкция trace
вне функции выводит глобальное значение переменной.
var str1:String = "Global"; function scopeTest () { var str1:String = "Local"; trace(str1); // Local } scopeTest(); trace(str1); // Global
56
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Переменные ActionScript в отличие от переменных в C++ и Java не имеют области действия уровня блока. Блоком программного кода является группа инструкций между открывающей фигурной скобкой ( {
) и закрывающей фигурной скобкой ( }
). В некоторых языках программирования, таких как C++ и Java, переменные, объявленные в блоке программного кода, недоступны вне этого блока кода. Это ограничение области действия называется областью действия уровня блока и не существует в ActionScript. Если переменная объявляется внутри блока программного кода, эта переменная будет доступна не только в этом блоке кода, но также во всех других частях функции, которой принадлежит этот блок кода. Например, следующая функция содержит переменные, которые определены в различных областях действия уровня блока. Все переменные доступны во всех частях функции. function blockTest (testArray:Array) { var numElements:int = testArray.length; if (numElements > 0) { var elemStr:String = "Element #"; for (var i:int = 0; i < numElements; i++) { var valueStr:String = i + ": " + testArray[i]; trace(elemStr + valueStr); } trace(elemStr, valueStr, i); // all still defined } trace(elemStr, valueStr, i); // all defined if numElements > 0 } blockTest(["Earth", "Moon", "Sun"]);
Интересным следствием отсутствия области действия уровня блока является возможность считывать и записывать переменные, которые еще не были объявлены, при условии, что они будут объявлены до конца функции. Это возможно благодаря технологии, называемой подъем, которая подразумевает перемещение всех объявлений переменных в верхнюю часть функции. Например, следующий программный код компилируется, несмотря на то что исходная функция trace()
для переменной num
появляется до того, как объявлена переменная num
.
trace(num); // NaN var num:Number = 10; trace(num); // 10
Однако компилятор не будет выполнять подъем каких-либо инструкций присваивания. Это объясняет, почему выполнение исходной функции trace()
для переменной num
в результате дает NaN (нечисловое значение), которое является значением по умолчанию для переменных с типом данных Number. Это означает, что можно назначать значения для переменных даже до того, как они будут объявлены, как показано в следующем примере.
num = 5; trace(num); // 5 var num:Number = 10; trace(num); // 10
57
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Значения по умолчанию
Значением по умолчанию является значение, которое содержит переменную перед тем, как ей будет установлено пользовательское значение. Инициализация переменной происходит при первой установке ее значения. Если объявляется переменная, но не устанавливается ее значение, эта переменная не инициализирована. Значение неинициализированной переменной зависит от ее типа данных. В следующей таблице описаны значения переменных по умолчанию, упорядоченные по типам данных.
Для переменных с типом Number значением по умолчанию является NaN (нечисловое значение), являющееся специальным значением, определенным стандартом IEEE-754 для передачи значений, не являющихся числами. Если определяется переменная, но не указывается ее тип данных, типом данных, применяемым по умолчанию, является *
, который фактически означает, что тип переменной не задан. Если также не инициализировать переменную без типа с помощью значения, значением по умолчанию для нее будет undefined
.
Для типов данных, отличных от Boolean, Number, int и uint, значением по умолчанию для любой неинициализированной переменной является null
. Это применимо ко всем классам, определяемым языком ActionScript 3.0, а также к любым создаваемым классам. Неопределенное значение null
не является действительным значением для переменных с типом Boolean, Number, int или uint. Если выполняется попытка назначить значение null
такой переменной, это значение преобразуется в значение по умолчанию для этого типа данных. Переменным с типом Object можно назначать значение null
. При попытке назначить значение undefined
переменной с типом Object, значение преобразуется в null
. Для переменных с типом Number существует специальная функция с названием isNaN()
, которая возвращает логическое значение true
, если переменная не число, и false
в ином случае.
Типы данных
Тип данных определяет набор значений. Например, тип данных Boolean является набором всего из двух значений: true
и false
. Помимо типа данных Boolean в ActionScript 3.0 определяется несколько более часто используемых типов данных, таких как строки (String), числовые значения (Number) и массивы (Array). Можно определить собственный тип данных, используя классы или интерфейсы для определения нестандартного набора значений. Все значение ActionScript 3.0, независимо от того, примитивные они или сложные, являются объектами. Тип данных Значение по умолчанию
Boolean
false
int 70
Число
NaN
Объект
null
String null
uint 70
Не объявлено (эквивалентно аннотации типа *
)
undefined
Все другие классы, включая определяемые пользователем классы.
null
58
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Примитивное значение — это значение, которое относится к одному из следующих типов данных: Boolean, int, Number, String и uint. Работать с примитивными значениями обычно получается быстрее, чем со сложными, поскольку ActionScript хранит примитивные значения специальным способом, делая возможным оптимизацию быстродействия и использования памяти. Примечание. Читателям, заинтересованным в технических подробностях, любопытно будет узнать, что внутренним форматом хранения примитивных значений в ActionScript являются постоянные объекты. Тот факт, что они хранятся как постоянные объекты, означает, что вместо передачи самих значений можно передавать ссылки на них. Это сократит потребление памяти и повысит скорость выполнения, поскольку ссылки обычно значительно меньше, чем сами значения.
Сложное значение — это альтернатива примитивным значениям. К типам данных, определяющих наборы сложных значений, относятся Array, Date, Error, Function, RegExp, XML и XMLList. Во многих языках программирования существуют различия между примитивными значениями и интерфейсными объектами. Например, в Java имеется примитивное значение int и класс java.lang.Integer, который служит интерфейсом к нему. Примитивы Java не являются объектами, но таковы их интерфейсные объекты, с помощью которых примитивы становятся пригодны для некоторых операций, а интерфейсные объекты лучше подходят для других операций. В ActionScript 3.0 в практических целях простые значения и их интерфейсные объекты неразличимы. Все значения, даже простые значения, являются объектами. Flash Player и Adobe AIR обрабатывают эти простые типы как особые случаи, поскольку они ведут себя как объекты, но при этом не требуют обычной нагрузки, связанной с созданием объектов. Это значит, что следующие две строки программного кода эквивалентны.
var someInt:int = 3; var someInt:int = new int(3);
Все примитивные и сложные типы данных, перечисленные выше, определяются классами ядра ActionScript 3.0. Классы ядра позволяют создавать объекты с помощью литеральных значений вместо использования оператора new
. Например, можно создать массив с помощью литерального значения или конструктора класса Array, как показано в следующем примере.
var someArray:Array = [1, 2, 3]; // literal value var someArray:Array = new Array(1,2,3); // Array constructor
Проверка типа
Проверка типа может производиться либо во время компиляции, либо во время выполнения. В языках статичного типа, таких как C++ и Java, проверка типа выполняется при компиляции. В языках динамического типа, таких как Smalltalk и Python, проверка типа возможна во время выполнения. Являясь языком динамического типа, ActionScript 3.0 позволяет проверку типа во время выполнения, но также поддерживает проверку типа при компиляции благодаря специальному режиму компиляции, называемому строгим режимом. В строгом режиме проверка типа происходит как во время компиляции, так и во время выполнения, а в стандартном режиме проверка возможна только во время выполнения.
Языки динамического типа предлагают значительную гибкость при структурировании программного кода, но иногда из-за этого происходят ошибки типов, которые обнаруживаются во время выполнения. В языках статического типа ошибки типов обнаруживаются во время компиляции, но для этого необходимо, чтобы информация о типе была известна во время компиляции.
59
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Проверка типа во время компиляции
Проверка типа во время компиляции часто более предпочтительна в крупных проектах, поскольку по мере роста проекта гибкость типов данных обычно становится менее важной, чем необходимость отслеживания ошибок на максимально ранних стадиях. Вот почему по умолчанию компилятор ActionScript в Adobe Flash CS4 Professional и Adobe Flex Builder установлен для работы в строгом режиме. Чтобы обеспечить возможность проверки во время компиляции, компилятору необходимо располагать сведениями о типах данных для переменных и выражений в программном коде. Чтобы явным образом объявить тип данных для переменной, добавьте оператор двоеточия (
:
) с последующим указанием типа данных в качестве суффикса к имени переменной. Чтобы связать тип данных с параметром, используется оператор двоеточия с последующим указанием типа данных. Например, в следующем программном коде к параметру xParam
добавляются сведения о типе данных, а затем объявляется переменная myParam
с явно указанным типом данных.
function runtimeTest(xParam:String) { trace(xParam); } var myParam:String = "hello"; runtimeTest(myParam);
В строгом режиме работы компилятор ActionScript сообщает о несоответствиях типов как об ошибках компиляции. Например, в следующем программном коде объявляется параметр функции xParam
с типом Object, но затем предпринимается попытка назначить этому параметру значения типа String и Number. При этом в строгом режиме работы компилятора выдаются ошибки.
function dynamicTest(xParam:Object) { if (xParam is String) { var myStr:String = xParam; // compiler error in strict mode trace("String: " + myStr); } else if (xParam is Number) { var myNum:Number = xParam; // compiler error in strict mode trace("Number: " + myNum); } }
Однако даже в строгом режиме можно селективно отключать проверку типа во время компиляции, оставляя незаполненной правую часть инструкции присваивания. Можно пометить переменную или выражение как не имеющие типа, либо пропустив аннотацию типа, либо используя специальную аннотацию типа с помощью звездочки (
*
). Например, если параметр xParam
в предыдущем примере изменяется так, что больше не имеет аннотации типа, программный код будет компилироваться в строгом режиме.
60
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
function dynamicTest(xParam) { if (xParam is String) { var myStr:String = xParam; trace("String: " + myStr); } else if (xParam is Number) { var myNum:Number = xParam; trace("Number: " + myNum); } } dynamicTest(100) dynamicTest("one hundred");
Проверка типа при выполнении
Проверки типа при выполнении в ActionScript 3.0 происходит независимо от того, идет работа в строгом или в стандартном режиме. Рассмотрите ситуацию, в которой значение 3 передается в качестве аргумента функции, ожидающей массив. В строгом режиме компилятор создаст ошибку, поскольку значение 3 не совместимо с типом данных Array. Если отключить строгий режим и выполнять программу в стандартном режиме, компилятор не заметит несоответствие типов, но проверка типа во время выполнения, осуществляемая в Flash Player и Adobe AIR, вызовет ошибку выполнения. В следующем примере показана функция с именем typeTest()
, которая ожидает аргумент Array, но ей передается значение 3. Это вызывает ошибку выполнения в стандартном режиме, поскольку значение 3 не является членом объявленного для параметра типа данных (Array).
function typeTest(xParam:Array) { trace(xParam); } var myNum:Number = 3; typeTest(myNum); // run-time error in ActionScript 3.0 standard mode
Также возможны ситуации, когда ошибки выполнения возникают при работе в строгом режиме. Это возможно в тех случаях, если используется строгий режим, но выключена проверка типа при компиляции при использовании переменных без указания типа. Если используются переменные без указания типа, проверка типа не отключается полностью, а просто откладывается до выполнения программного кода. Например, если для переменной myNum
в предыдущем примере не объявлен тип данных, компилятор не сможет определить несоответствие типов, но программы Flash Player и Adobe AIR выдадут ошибку выполнения, поскольку в них сравнивается значение при выполнении myNum
, для которого с помощью инструкции присваивания установлено значение 3, с типом xParam
, для которого задан тип данных Array.
function typeTest(xParam:Array) { trace(xParam); } var myNum = 3; typeTest(myNum); // run-time error in ActionScript 3.0
61
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Проверка типа при выполнении позволяет более гибко использовать наследование, чем при проверке во время компиляции. Откладывая проверку типа до времени выполнения, стандартный режим позволяет ссылаться на свойства подкласса даже в том случае, если выполняется восходящее преобразование. Восходящее преобразование происходит, если для объявления типа экземпляра класса используется базовый класс, а для его инициации используется подкласс. Например, можно создать класс с именем ClassBase, который может быть расширен (классы с атрибутом final
не могут быть расширены).
class ClassBase { }
Затем можно создать подкласс ClassBase с именем ClassExtender, у которого есть одно свойство с именем someString
, как показано в следующем примере.
class ClassExtender extends ClassBase { var someString:String; }
Используя оба класса, можно создать экземпляр класса, объявляемый с типом данных ClassBase, но инициируемый с помощью конструктора ClassExtender. Восходящее преобразование считается безопасной операцией, поскольку базовый класс не содержит каких-либо свойств или методов, которых не было бы в подклассе.
var myClass:ClassBase = new ClassExtender();
В то же время подкласс содержит свойства или методы, которые отсутствуют в базовом классе. Например, класс ClassExtender содержит свойство someString
, не существующее в классе ClassBase. В стандартном режиме работы ActionScript 3.0 можно ссылаться на это свойство с помощью экземпляра myClass
, не создавая ошибки во время компиляции, как показано в следующем примере. var myClass:ClassBase = new ClassExtender(); myClass.someString = "hello"; // no error in ActionScript 3.0 standard mode
Оператор is
Оператор is
, который впервые появился только в ActionScript 3.0, позволяет проверить, являются ли переменная или выражение членом определенного типа данных. В предыдущих версиях ActionScript оператор instanceof
обеспечивал данную функциональную возможность, но в ActionScript 3.0 оператор instanceof
не следует использовать для проверки принадлежности к типу данных. Оператор is
необходимо использовать вместо оператора instanceof
для проверки типа вручную, поскольку выражение x instanceof y
проверяет только цепочку прототипа x
на существование y
(а в ActionScript 3.0 цепочка прототипа не передает полной картины иерархии наследования). Оператор is
проверяет правильность иерархии наследования и может применяться для проверки не только того, является ли объект экземпляром определенного класса, но также является ли объект экземпляром класса, реализующего определенный интерфейс. В следующем примере создается экземпляр класса Sprite с именем mySprite
, который использует оператор is
для проверки того, является ли mySprite
экземпляром классов Sprite и DisplayObject, а также реализует ли он интерфейс IEventDispatcher. var mySprite:Sprite = new Sprite(); trace(mySprite is Sprite); // true trace(mySprite is DisplayObject);// true trace(mySprite is IEventDispatcher); // true
62
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Оператор is
проверяет иерархию наследования и правильно диагностирует, что mySprite
совместим с классами Sprite и DisplayObject (класс Sprite является подклассом класса DisplayObject). Оператор is
также проверяет, действительно ли mySprite
наследует от какого-либо класса, в котором реализован интерфейс IEventDispatcher. Поскольку класс Sprite наследует от класса EventDispatcher, в котором реализован интерфейс IEventDispatcher, оператор is
правильно сообщает, что в классе mySprite
также реализован этот интерфейс. В следующем примере показаны те же тесты из предыдущего примера, но с оператором instanceof
вместо оператора is
. Оператор instanceof
правильно определяет, что класс mySprite
является экземпляром классов Sprite или DisplayObject, но он возвращает результат false
при попытке проверить, реализует ли класс mySprite
интерфейс IEventDispatcher.
trace(mySprite instanceof Sprite); // true trace(mySprite instanceof DisplayObject);// true trace(mySprite instanceof IEventDispatcher); // false
Оператор as
Оператор as
, который впервые появился в ActionScript 3.0, также позволяет проверять, является ли выражение членом указанного типа данных. В отличие от оператора is
оператор as
не возвращает логические значения. При этом оператор as
возвращает значение выражения вместо true
или значение null
вместо false
. В следующем примере показан результат использования оператора as
вместо оператора is
в простом случае проверки. Определяется, действительно ли экземпляр Sprite является членом типов данных DisplayObject, IEventDispatcher и Number.
var mySprite:Sprite = new Sprite(); trace(mySprite as Sprite); // [object Sprite] trace(mySprite as DisplayObject); // [object Sprite] trace(mySprite as IEventDispatcher); // [object Sprite] trace(mySprite as Number); // null
При использовании оператора as
операнд справа должен быть типом данных. Попытка использовать в качестве операнда справа выражение вместо типа данных приведет к ошибке.
Динамические классы
Динамический класс определяет объект, который может быть изменен во время выполнения путем добавления или изменения свойств и методов. Не динамические классы, такие как класс String, являются запечатанными классами. К запечатанным классам нельзя добавлять свойства или методы во время выполнения. Динамический класс создается с помощью атрибута dynamic
при объявлении класса. Например, в следующем программном коде создается динамический класс с именем Protean
. dynamic class Protean { private var privateGreeting:String = "hi"; public var publicGreeting:String = "hello"; function Protean() { trace("Protean instance created"); } }
63
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Если затем будет инициирован экземпляр класса Protean
, то к нему можно будет добавлять свойства и методы, не изменяя определение этого класса. Например, в следующем программном коде создается экземпляр класса Protean
и к нему добавляется свойство с именем aString
, а также свойство с именем aNumber
.
var myProtean:Protean = new Protean(); myProtean.aString = "testing"; myProtean.aNumber = 3; trace(myProtean.aString, myProtean.aNumber); // testing 3
Свойства, добавленные к экземпляру динамического класса, являются объектами выполнения, поэтому любые проверки типов выполняются во время выполнения. Нельзя добавить аннотацию типа к свойству, добавленному таким образом.
Также к экземпляру myProtean
можно добавить метод, определив функцию и прикрепив ее к свойству экземпляра myProtean
. В следующем программном коде инструкция трассировки перемещается в метод с именем traceProtean()
.
var myProtean:Protean = new Protean(); myProtean.aString = "testing"; myProtean.aNumber = 3; myProtean.traceProtean = function () { trace(this.aString, this.aNumber); }; myProtean.traceProtean(); // testing 3
Методы, созданные таким способом, не имеют доступа к любым частным свойствам или методам класса Protean. Более того, даже ссылки на общие свойства или методы класса Protean
должны уточняться с помощью ключевого слова this
или имени класса. В следующем примере показан метод traceProtean()
, пытающийся обращаться к частным или общим переменным класса Protean
. myProtean.traceProtean = function () { trace(myProtean.privateGreeting); // undefined trace(myProtean.publicGreeting); // hello }; myProtean.traceProtean();
Описания типов данных
К примитивным типам данных относятся Boolean, int, Null, Number, String, uint и void. Классы ядра ActionScript также определяют следующие сложные типы данных: Object, Array, Date, Error, Function, RegExp, XML и XMLList. Логический тип данных (Boolean) Логический (Boolean) тип данных состоит из двух значений: true
и false
. Никакие другие значения для переменных с типом Boolean не действительны. По умолчанию для переменной с типом Boolean, которая объявлена, но не инициализирована, устанавливается значение false
.
Тип данных int
Тип данных int предназначен для внутреннего хранения информации в виде 32-разрядных целых чисел, включает подмножество целых чисел от 64
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
-2147483648 (-2
31
) до 2147483647 (2
31
- 1) включительно. В предыдущих версиях ActionScript предлагался только тип данных Number, в котором использовались как целые числа, так и числа с плавающей точкой. В ActionScript 3.0 теперь есть доступ к двоичным типам нижнего уровня для работы с 32-разрядными целыми числами со знаком и без знака. Если переменная не использует числа с плавающей точкой, то применение типа данных int вместо типа данных Number позволит ускорить и сделать более эффективной обработку данных. Для целых значений, выходящих за пределы диапазона минимального и максимального значений, используйте тип данных Number, с помощью которого можно обрабатывать значения в промежутке между положительным и отрицательным значением 9007199254740992 (53-разрядные целые значения). По умолчанию значение переменной с типом данных int равно 0.
Тип данных Null
Тип данных Null содержит только одно значение null
. Это значение по умолчанию для типа данных String и всех классов, которые определяют сложные типы данных, включая класс Object. Никакой другой из примитивных типов данных, таких как Boolean, Number, int и uint, не может содержать null
. Flash Player и Adobe AIR будут преобразовывать значение null
в соответствующее значение по умолчанию, если попытаться присвоить null
переменным типа Boolean, Number, int или uint. Нельзя использовать этот тип данных в качестве аннотации типа.
Тип данных Number
В ActionScript 3.0 тип данных Number может быть представлен целыми числами, целыми числами без знака, а также числами с плавающей точкой. В то же время, чтобы повысить производительность, необходимо использовать тип данных Number только для целых значений, которые не помещаются в 32-разрядных типах int
и uint
, или для значений с плавающей точкой. Для сохранения числа с плавающей точкой включите в него десятичную точку. Если пропустить десятичную точку, число будет сохранено как целое.
В типе данных Number используется 64-разрядный формат с двойной точностью в соответствии со стандартом IEEE для двоичных арифметических операций с плавающей точкой (IEEE-754). Этот стандарт определяет, как числа с плавающей точкой сохраняются с помощью 64 доступных разрядов. Один разряд используется для обозначения того, положительным или отрицательным является число. Одиннадцать разрядов используются для экспоненциальной части, которая сохраняется с основанием 2. Оставшиеся 52 разряда используются для хранения значащей части числа (также называемой мантиссой), которая является числом, возводимым в степень, указанную в экспоненциальной части.
Используя некоторые из этих разрядов для хранения экспоненциальной части, тип данных Number может сохранять числа с плавающей точкой, значительно превышающие значения, которые бы получались, если бы все разряды были отведены под значащую часть числа. Например, если бы тип данных Number использовал все свои 64 разряда для сохранения значащей части числа, в нем можно было бы сохранить значение 2
65
- 1. Используя 11 разрядов для хранения экспоненциальной части, тип данных Number может возводить свою значимую часть в степень 2
1023
. Максимальное и минимальное значения, которые может воспроизводить класс Number, хранятся в статических свойствах класса Number, называемых Number.MAX_VALUE
и Number.MIN_VALUE
.
Number.MAX_VALUE == 1.79769313486231e+308 Number.MIN_VALUE == 4.940656458412467e-324
65
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Расплатой за возможность использовать столь огромный диапазон значений является точность. Тип данных Number использует 52 разряда для хранения значимой части числа, в результате числа, которым требуется больше 52 разрядов для точного воспроизведения, например 1/3, отображаются как приближенные значения. Если для приложения требуется абсолютная точность в работе с десятичными числами, необходимо использовать программное обеспечение, реализующее десятичные арифметические операции с плавающей точкой в качестве альтернативы двоичным операциям.
При сохранении целых значений с помощью типа данных Number для значимой части числа используется только 52 разряда. Тип данных Number использует эти 52 разряда и специальный скрытый разряд для представления целых чисел в диапазоне от -9007199254740992 (-2
53
) до 9007199254740992 (2
53
).
Flash Player и Adobe AIR используют значение NaN
не только как значение по умолчанию для переменных с типом Number
, но также в качестве результата любой операции, которая должна была вернуть число, но не сделала этого. Например, при попытке рассчитать квадратный корень отрицательного числа результатом будет NaN
. Другими специальным значениями типа Number являются плюс бесконечность и минус бесконечность
.
Примечание. Результатом деления на 0
является только NaN
, если делитель тоже 0
. В результате деления на 0
получается infinity
, если делимое положительно, или -infinity
, если делимое отрицательно.
Тип данных String
Тип данных String передает последовательность 16-разрядных символов. Для внутреннего хранения значений с типом String используются символы Unicode и формат UTF-16. Значения с типом данных String являются постоянными, такими же, как и при программировании в языке Java. Операция со значением String возвращает новый экземпляр этой строки. По умолчанию значением для переменной, объявленной с типом данных String, является null
. Значение null
не то же самое, что и пустая строка (
""
), несмотря на то, что оба эти значения отражают отсутствие каких-либо символов.
Тип данных uint
Для внутреннего хранения типа данных uint используется 32-разрядные целые числа без знака. Этот тип данных содержит диапазон целых значений от 0 до 4294967295 (2
32
- 1), включительно. Тип данных uint применяется в особых случаях, когда необходимы положительные целые числа. Например, следует использовать тип данных uint для передачи значений цвета пикселя, поскольку тип данных int имеет внутренний разряд для знака, не удобный для обработки цветовых значений. Для целых значений, больших, чем максимальное значение uint, следует использовать тип данных Number, который позволяет обрабатывать 53-разрядные целые значения. По умолчанию значение переменной с типом данных uint равно 0.
Тип данных void
Тип данных void содержит только одно значение undefined
. В предыдущих версиях ActionScript значение undefined
было значением по умолчанию для экземпляров класса Object. В ActionScript 3.0 значением по умолчанию для экземпляров Object является null
. Если попытаться назначить значение undefined
экземпляру класса Object, то Flash Player или Adobe AIR преобразуют значение в null
. Переменной, для которой не задан тип, можно назначить только значение undefined
. Переменные без указания типа — это переменные, для которых либо отсутствует любая аннотация типа, либо указан символ звездочки (
*
) в качестве аннотации типа. Значение void
можно использовать только для аннотации возвращаемого типа.
66
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Тип данных Object
Тип данных Object определяется классом Object. Класс Object служит базовым классом для всех определений классов в ActionScript. В ActionScript 3.0 версия типа данных Object отличается от предыдущих версий тремя особенностями. Во-первых, тип данных Object больше не является типом данных по умолчанию, назначаемым переменным, для которых не задан тип. Во-вторых, тип данных Object больше не включает значение undefined
, которое используется в качестве значения по умолчанию для экземпляров Object. В-третьих, в ActionScript 3.0 значением по умолчанию для экземпляров класса Object является null
.
В предыдущих версиях ActionScript переменной без аннотации типа автоматически назначался тип Object. В ActionScript 3.0 это не так, здесь реализована концепция переменной, действительно не имеющей типа. Переменные без аннотации типа теперь расцениваются как переменные не имеющие типа. Если требуется, чтобы читателям программного кода были ясны намерения автора оставить переменную без типа, можно использовать новый символ звездочка (
*
) для аннотации типа, что будет эквивалентно пропущенной аннотации типа. В следующем примере показаны две эквивалентные инструкции, обе они объявляют переменную x
, не имеющую типа.
var x var x:*
Только переменная, не имеющая типа, может содержать значение undefined
. Если попытаться назначить значение undefined
переменной, имеющей тип данных, Flash Player или Adobe AIR преобразует значение undefined
в значение этого типа данных по умолчанию. Для экземпляров с типом данных Object значением по умолчанию является null
, и это означает, что Flash Player или Adobe AIR будут преобразовывать значение undefined
в null
, если попытаться назначить undefined
экземпляру Object.
Преобразования типа
Преобразование типа происходит, если значение превращается из одного типа данных в другой. Преобразование типа может быть либо явным, либо подразумеваемым. Неявное преобразование, которое также называется неявным приведением, иногда выполняется при выполнении Flash Player или Adobe AIR. Например, если значение 2 назначено переменной с типом данных Boolean, программы Flash Player или Adobe AIR преобразуют значение 2 в логическое значение true
, перед тем как назначать его переменной. Явное преобразование, которое также называется явным приведением, происходит в тех случаях, когда программный код запрашивает, чтобы компилятор переменную одного типа данных обработал как переменную другого типа. Если используются примитивные значения, явное приведение преобразует значения из одного типа данных в другой. Для явного приведения объекта к другому типу имя этого объекта заключают в круглые скобки и предваряют именем нового типа. Например, в следующем программном коде берется логическое значение и явным образом приводится к целому числу.
var myBoolean:Boolean = true; var myINT:int = int(myBoolean); trace(myINT); // 1
Неявные преобразования
Неявные преобразования происходят при выполнении программ в ряде следующих случаев.
•
В инструкциях присваивания
•
Если значения передаются как аргументы функции
•
Если значения возвращаются из функции
•
В выражениях, использующих определенные операторы, например оператор добавления (
+
)
67
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Для определенных пользователем типов неявные преобразования выполняются успешно, если преобразуемое значение является экземпляром целевого класса или класса, производного от целевого. Если неявное преобразование завершается неудачно, происходит ошибка. Например, в следующем программном коде происходит успешное неявное преобразование и неудачное неявное преобразование.
class A {} class B extends A {} var objA:A = new A(); var objB:B = new B(); var arr:Array = new Array(); objA = objB; // Conversion succeeds. objB = arr; // Conversion fails.
Для примитивных типов неявные преобразования обрабатываются путем вызова тех же внутренних алгоритмов преобразования, которые вызываются функциями явного преобразования. В следующих разделах подробно обсуждаются преобразования этих примитивных типов.
Явные преобразования
Очень полезно использовать явные преобразования, или явные приведения, если компиляция происходит в строгом режиме, поскольку возможны случаи, когда требуется, чтобы при несовпадении типов не создавались ошибки во время компиляции. Такая ситуация может возникать, когда известно, что при неявном приведении значения будут правильно преобразованы во время выполнения. Например, при обработке данных, полученных из формы, можно возложить на явное приведение преобразования определенных строковых значений в числовые значения. В следующем программном коде создается ошибка во время компиляции, даже несмотря на то, что этот код будет выполняться верно в стандартном режиме.
var quantityField:String = "3"; var quantity:int = quantityField; // compile time error in strict mode
Если требуется продолжить работу в строгом режиме, но необходимо преобразовывать строки в целые значения, можно использовать явное преобразование, делая это следующим образом.
var quantityField:String = "3"; var quantity:int = int(quantityField); // Explicit conversion succeeds.
Явное приведение в int, uint и Number
Можно выполнять явное приведение любого типа данных в один из трех числовых типов: int, uint и Number. Если Flash Player или Adobe AIR не может преобразовать число по определенной причине, типам данных int и uint по умолчанию назначается значение 0, а типу данных Number — значение NaN
. Если происходит преобразование логического значения в числовое, то true
становится значением 1, а false
значением 0.
var myBoolean:Boolean = true; var myUINT:uint = uint(myBoolean); var myINT:int = int(myBoolean); var myNum:Number = Number(myBoolean); trace(myUINT, myINT, myNum); // 1 1 1 myBoolean = false; myUINT = uint(myBoolean); myINT = int(myBoolean); myNum = Number(myBoolean); trace(myUINT, myINT, myNum); // 0 0 0
68
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Строковые значения, содержащие только числа, могут быть успешно преобразованы в один из цифровых типов. В числовые типы также можно преобразовывать строки, которые похожи на отрицательные значения, или строки, отображающие шестнадцатеричные значения (например, 0x1A
). В процессе преобразования отбрасываются предшествующий или завершающий символы пробелов в строковых значениях. Также можно выполнить явное приведение строк, которые напоминают числа с плавающей точкой, используя тип данных Number()
. Включение десятичной точки заставляет значения с типом uint()
и int()
возвращать целое значение, отбрасывая десятичную часть и следующие за ней символы. Например, следующие строковые значения могут быть явным образом приведены в числа.
trace(uint("5")); // 5 trace(uint("-5")); // 4294967291. It wraps around from MAX_VALUE trace(uint(" 27 ")); // 27 trace(uint("3.7")); // 3 trace(int("3.7")); // 3 trace(int("0x1A")); // 26 trace(Number("3.7")); // 3.7
При сохранении значений, содержащих нечисловые символы, возвращается 0, если выполнялось явное приведение в int()
или uint()
, а также NaN
, если выполнялось явное приведение в Number()
. В процессе преобразования предшествующие или завершающие пробелы отбрасываются, но возвращается 0 или NaN
, если строка содержит пробел, разделяющий два числа.
trace(uint("5a")); // 0 trace(uint("ten")); // 0 trace(uint("17 63")); // 0
В ActionScript 3.0 функция Number()
больше не поддерживает восьмеричные (имеющие основание 8) числа. Если передается строка, начинающаяся с 0 в функцию Number()
ActionScript 2.0, это число интерпретируется как восьмеричное и преобразуется в свой десятеричный эквивалент. Это изменилось в функции Number()
в ActionScript 3.0, которая просто отбрасывает первый ноль. Например, в следующем программном коде создаются разные выходные данные при компиляции в разных версиях ActionScript.
trace(Number("044")); // ActionScript 3.0 44 // ActionScript 2.0 36
В явном приведении нет необходимости, если значение одного числового типа назначается переменной другого числового типа. Даже в строгом режиме числовые типы неявным образом преобразуются в другие числовые типы. Это означает, что в некоторых случаях, когда нарушаются диапазоны значений типа, могут выдаваться неожиданные значения. В следующих примерах все компиляции выполняются в строгом режиме, но в некоторых случаях все равно будут создаваться неожиданные значения.
var myUInt:uint = -3; // Assign int/Number value to uint variable trace(myUInt); // 4294967293 var myNum:Number = sampleUINT; // Assign int/uint value to Number variable trace(myNum) // 4294967293 var myInt:int = uint.MAX_VALUE + 1; // Assign Number value to uint variable trace(myInt); // 0 myInt = int.MAX_VALUE + 1; // Assign uint/Number value to int variable trace(myInt); // -2147483648
В следующей таблице резюмированы результаты явного приведения в типы Number, int или uint из других типов данных.
69
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Явное приведение в Boolean
Явное приведение в Boolean из любого числового типа данных (uint, int и Number) дает значение false
, если числовое значение равно 0, и true
в остальных случаях. Для типа данных Number значение NaN
также преобразуется в false
. В следующем примере показаны результаты явного приведения чисел -1, 0 и 1.
var myNum:Number; for (myNum = -1; myNum<2; myNum++) { trace("Boolean(" + myNum +") is " + Boolean(myNum)); }
В результирующих данных примера показано, что из трех чисел только для 0 было возвращено значение false
.
Boolean(-1) is true Boolean(0) is false Boolean(1) is true
Явное приведение в Boolean из значения String возвращает false
, если значение строки null
или это пустая строка (
""
). Во всех остальных случаях возвращается значение true
.
var str1:String; // Uninitialized string is null. trace(Boolean(str1)); // false var str2:String = ""; // empty string trace(Boolean(str2)); // false var str3:String = " "; // white space only trace(Boolean(str3)); // true
Явное приведение в Boolean экземпляра класса Object возвращает false
, если значение экземпляра null
; в остальных случаях возвращается значение true
:
var myObj:Object; // Uninitialized object is null. trace(Boolean(myObj)); // false myObj = new Object(); // instantiate trace(Boolean(myObj)); // true
Тип данных или значение
Результат преобразования в Number, int или uint
Boolean Если значение равно true
, преобразуется в 1; иначе — в 0.
Date Внутреннее представление объекта Date, показывающее число миллисекунд, которые прошли начиная с полуночи 1 января 1970 года, универсальное время.
null
70
Объект Если значение экземпляра null
и он преобразуется в Number, получается значение NaN
; иначе получается значение 0.
String Число, если Flash Player или Adobe AIR смогут преобразовать строку в формат Number; иначе — NaN
, если преобразуется в Number, или 0, если преобразуется в int или uint.
undefined
Если преобразуется в Number, получается NaN
; если преобразуется в int или uint — 0.
70
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Для переменных с типом Boolean выполняется специальная обработка в строгом режиме, при которой этим переменным можно назначить значения с любым типом данных, не проводя явного приведения. Неявное приведение из всех типов данных в тип данных Boolean происходит даже в строгом режиме. Говоря другими словами, в отличие практически от всех других типов данных, явное приведение в Boolean никогда не требуется, чтобы избежать ошибок в строгом режиме. В следующих примерах все компиляции выполняются в скрытом режиме и ведут себя так, как предполагается во время выполнения.
var myObj:Object = new Object(); // instantiate var bool:Boolean = myObj; trace(bool); // true bool = "random string"; trace(bool); // true bool = new Array(); trace(bool); // true bool = NaN; trace(bool); // false
В следующей таблице резюмированы результаты явного приведения в типы Boolean из других типов данных.
Явное приведение в String
Явное приведение к типу данных String из любого числового типа данных возвращает строку, отображающую данное число. Явное приведение к типу данных String логического значения (Boolean) возвращает строку "true"
, если значение true
; возвращает строку "false"
, если значение false
.
Явное приведение типа данных String из значения экземпляра класса Object возвращает строку "null"
, если значение этого экземпляра null
. В остальных случаях явное приведение типа String из значения класса Object возвращает строку "[object Object]"
.
Явное приведение в String из экземпляра класса Array возвращает строку, состоящую из разделенного запятыми списка всех элементов этого массива. Например, в следующем явном приведении к типу данных String возвращается одна строка, содержащая все три элемента массива.
var myArray:Array = ["primary", "secondary", "tertiary"]; trace(String(myArray)); // primary,secondary,tertiary
Явное приведение к типу String из экземпляра класса Date возвращает строчное представление даты, содержащейся в данном экземпляре. Например, в следующем примере возвращается строчное представление экземпляра класса Date (на выходе показан результат для тихоокеанского поясного времени).
var myDate:Date = new Date(2005,6,1); trace(String(myDate)); // Fri Jul 1 00:00:00 GMT-0700 2005
В следующей таблице резюмированы результаты явного приведения в типы String из других типов данных.
Тип данных или значение Результат преобразования в Boolean
String
false
, если значение null
или пустая строка (
""
); true
во всех остальных случаях.
null false
Number, int или uint
false
, если значение NaN
или 0; true
во всех остальных случаях.
Объект
false
, если значение экземпляра null
; true
во всех остальных случаях.
71
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Синтаксис
Синтаксис языка определяет набор правил, которые следует соблюдать при написании исполняемого программного кода.
Чувствительность к регистру Язык ActionScript 3.0 чувствителен к регистру. Идентификаторы, различающиеся только значением регистра, считаются разными идентификаторами. Например, в следующем программном коде создаются две разные переменные.
var num1:int; var Num1:int;
Синтаксис с точкой
Оператор точка (
.
) обеспечивает способ доступа к свойствам и методам объекта. Используя синтаксис с точкой, можно обращаться к свойствам или методам класса по имени экземпляра, указывая за оператором точка имя требуемого свойства или метода. Например, рассмотрим следующее определение класса.
class DotExample { public var prop1:String; public function method1():void {} }
Используя синтаксис с точкой, можно обратиться к свойству prop1
и методу method1()
, применяя имя экземпляра, созданного в следующем программном коде.
var myDotEx:DotExample = new DotExample(); myDotEx.prop1 = "hello"; myDotEx.method1();
Можно использовать синтаксис с точкой при определении пакетов. Оператор точка используется для обращения ко вложенным пакетам. Например, класс EventDispatcher находится в пакете с именем events, который вложен в пакет с именем flash. Можно обратиться к пакету events, используя следующее выражение.
flash.events
Также к классу EventDispatcher можно обратиться, используя следующее выражение.
flash.events.EventDispatcher
Тип данных или значение Результат преобразования в String
Array Строка, содержащая все элементы массива.
Boolean
"true"
или "false"
Date Строка, отображающая объект Date.
null"null"
Number, int или uint Строчное представление данного числа.
Объект Если значение экземпляра null, возвращает "null"
; во всех остальных случаях "[object Object]".
72
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Синтаксис с косой чертой
Синтаксис с косой чертой не поддерживается в ActionScript 3.0. Синтаксис с косой чертой использовался в предыдущих версиях ActionScript для указания пути к фрагменту ролика или переменной.
Литералы
Литерал — это значение, которое появляется непосредственно в программном коде. Следующие примеры все являются литералами.
17 "hello" -3 9.4 null undefined true false
Литералы также могут группироваться, образуя составные литералы. Литералы массивов обрамляются квадратными скобками (
[]
) и используют запятые для разделения элементов массива. Литерал массива можно использовать для инициализации массива. В следующем примере показаны два массива, инициализируемые с помощью литералов. Можно использовать инструкцию new
и передать составной литерал в качестве параметра конструктору класса Array, но также можно назначить литеральные значения непосредственно при инициализации экземпляров следующих классов ядра ActionScript: Object, Array, String, Number, int, uint, XML, XMLList и Boolean.
// Use new statement. var myStrings:Array = new Array(["alpha", "beta", "gamma"]); var myNums:Array = new Array([1,2,3,5,8]); // Assign literal directly. var myStrings:Array = ["alpha", "beta", "gamma"]; var myNums:Array = [1,2,3,5,8];
Литералы также можно использовать для инициализации родового объекта. Родовой объект — это экземпляр класса Object. Литералы объекта заключаются в фигурные скобки (
{}
) и используют запятую для разделения свойств объекта. Каждое свойство объявляется с помощью символа двоеточия (
:
), который отделяет имя свойства от его значения. Можно создать родовой объект, используя инструкцию new
, а затем передать литерал объекта в качестве параметра конструктору класса Object, также можно назначить литерал объекта напрямую объявляемому экземпляру. В следующем примере продемонстрированы два альтернативных способа создания нового родового объекта и инициализации этого объекта с тремя свойствами (
propA
, propB
и propC
), каждое с установленным значением 1, 2 и 3 соответственно.
// Use new statement and add properties. var myObject:Object = new Object(); myObject.propA = 1; myObject.propB = 2; myObject.propC = 3; // Assign literal directly. var myObject:Object = {propA:1, propB:2, propC:3};
73
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Дополнительные сведения см. в разделах «Основные сведения о строках» на странице 152, «Основы регулярных выражений» на странице 221 и «Инициализация переменных XML» на странице 251.
Точки с запятой
Можно использовать символ точки с запятой (
;
) для завершения инструкции. В качестве альтернативы, если пропустить символ точки с запятой, компилятор предположит, что каждая строчка программного кода отображает отдельную инструкцию. Поскольку многие программисты привыкли использовать току с запятой для обозначения конца инструкции, программный код может быть удобнее для чтения, если согласованно использовать точки с запятой для завершения инструкций.
Использование точки с запятой для завершения инструкции позволяет поместить в одну строку больше одной инструкции, но при этом программный код становится менее удобочитаем.
Скобки В ActionScript 3.0 можно использовать скобки (
()
) тремя способами. Во-первых, можно использовать скобки для изменения порядка операций в выражении. Операции, которые группируются в скобках, всегда выполняются первыми. Например, скобки используются для смены порядка операций в следующем программном коде.
trace(2 + 3 * 4); // 14 trace((2 + 3) * 4); // 20
Во-вторых, можно использовать скобки с оператором запятая (
,
) для вычисления ряда выражений и возврата результата окончательного выражения, как показано в следующем примере.
var a:int = 2; var b:int = 3; trace((a++, b++, a+b)); // 7
В-третьих, можно использовать скобки для передачи одного или нескольких параметров функциям или методам, как показано в следующем примере, в котором значение String передается функции trace()
.
trace("hello"); // hello
Комментарии Программный код ActionScript 3.0 поддерживает два типа комментариев: однострочные комментарии и многострочные комментарии. Механизмы этих комментариев сходны с аналогичными механизмами в языках C++ и Java. Компилятор не будет обращать внимание на текст, помеченный как комментарий. Однострочный комментарий начинается с двух косых черт (
//
) и продолжается до конца строки. Например, в следующем программном коде содержится однострочный комментарий. var someNumber:Number = 3; // a single line comment
Многострочные комментарии начинаются с косой черты и звездочки (
/*
) и заканчиваются звездочкой и косой чертой (
*/
). /* This is multiline comment that can span more than one line of code. */
74
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Ключевые слова и зарезервированные слова Зарезервированные слова — это слова, которые нельзя использовать в качестве идентификаторов в программном коде, потому что эти слова зарезервированы для применения в ActionScript. Зарезервированные слова включают лексические ключевые слова, которые удаляются компилятором из пространства имен программы. Компилятор будет сообщать об ошибке, если какое-либо лексическое ключевое слово будет использоваться в качестве идентификатора. В следующей таблице перечислен список лексических ключевых слов ActionScript 3.0. Существует небольшое подмножество ключевых слов, называемых синтаксическими ключевыми словами, которые могут использоваться как идентификаторы, но при этом имеют специальное значение в определенных контекстах. В следующей таблице перечислен список синтаксических ключевых слов ActionScript 3.0.
Также существует несколько идентификаторов, которые иногда упоминаются как зарезервированные для будущего использования слова. Эти идентификаторы не зарезервированы в ActionScript 3.0, хотя некоторые из них могут расцениваться как ключевые слова программным обеспечением для работы с ActionScript 3.0. Многие из этих идентификаторов можно использовать в программном коде, но корпорация Adobe не рекомендует использовать их, поскольку они могут оказаться ключевыми словами в последующих версиях языка ActionScript. as break case catch
class const continue default
delete do else extends
false finally for function
if implements import in
instanceof interface internal is
native new null package
private protected public return
super switch this throw
to true try typeof
use var void while
with
each get set namespace
include dynamic final native
override static
abstract boolean byte cast
char debugger double enum
export float goto intrinsic
75
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Константы
ActionScript 3.0 поддерживает инструкцию const
, с помощью которой можно создавать константы. Константами называют свойства с фиксированным значением, которое нельзя изменить. Значение константе можно присвоить только один раз, и это назначение должно происходить в непосредственной близости от объявления это константы. Например, если константа объявлена в качестве члена одного класса, можно назначить значение константе только в самом ее объявлении или внутри конструктора класса. В следующем программном коде объявляются две константы. Первой константе, MINIMUM
, значение назначается в инструкции объявления константы. Второй константе, MAXIMUM
, значение назначается в конструкторе. Обратите внимание, что этот пример компилируется только в стандартном режиме, поскольку с строгом режиме значения константам разрешено присваивать только во время инициализации.
class A { public const MINIMUM:int = 0; public const MAXIMUM:int; public function A() { MAXIMUM = 10; } } var a:A = new A(); trace(a.MINIMUM); // 0 trace(a.MAXIMUM); // 10
Если попытать присвоить исходное значение константе любым другим способом, произойдет ошибка. Например, если предпринимается попытка установить исходное значение свойства MAXIMUM
вне данного класса, произойдет ошибка выполнения.
class A { public const MINIMUM:int = 0; public const MAXIMUM:int; } var a:A = new A(); a["MAXIMUM"] = 10; // run-time error
ActionScript 3.0 определяет широкий диапазон готовых к использованию констант. В соответствии с соглашением, константы в ActionScript обозначаются заглавными буквами с разделением слов символом подчеркивания (
_
). Например, определение класса MouseEvent использует соглашение об именовании своих констант, каждая из которых отражает событие, связанное с вводом данных мышью.
long prototype short synchronized
throws to transient type
virtual volatile
76
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
package flash.events { public class MouseEvent extends Event { public static const CLICK:String = "click"; public static const DOUBLE_CLICK:String = "doubleClick"; public static const MOUSE_DOWN:String = "mouseDown"; public static const MOUSE_MOVE:String = "mouseMove"; ... } }
Операторы
Операторы являются специальными функциями, принимающими один или несколько операндов и возвращающими значения. Операнд — это значение, обычно литерал, переменная или выражение, которые оператор использует в качестве входных данных. Например, в следующем программном коде операторы сложения (
+
) и умножения (
*
) используются с тремя литеральными операндами (2, 3 и 4
)
для получения значения. Это значение затем используется оператором присваивания (
=
), чтобы назначить возвращаемое значение, 14, переменной
sumNumber
.
var sumNumber:uint = 2 + 3 * 4; // uint = 14
Операторы могут быть унитарными, бинарными или тернарными. Унитарный оператор принимает один операнд. Например, оператор инкрементального увеличения (
++
) является унитарным оператором, поскольку он принимает только один операнд. Бинарный оператор принимает два операнда. Например, оператор деления (
/
) принимает два операнда. Тернарный оператор принимает три операнда. Например, оператор условия (
?:
) принимает три операнда.
Некоторые операторы являются перегруженными, это означает, что они ведут себя по-разному в зависимости от типа или количества переданных им операндов. Оператор сложения (
+
) является примером перегруженного оператора, который ведет себя по-разному в зависимости от типа операндов. Если оба операнда являются числами, оператор сложения возвращает сумму этих значений. Если оба операнда являются строками, оператор сложения возвращает последовательное соединение двух операндов. В следующем программном коде показано, как оператор по-разному ведет себя в зависимости от операндов.
trace(5 + 5); // 10 trace("5" + "5"); // 55
Поведение операторов также может отличаться в зависимости от числа передаваемых операндов. Оператор вычитание (
-
) является одновременно унарным и бинарным оператором. Если оператор вычитание используется только с одним операндом, оператор меняет его знак и возвращает результат. Если оператор вычитания используется с двумя операндами, он возвращает разность между ними. В следующем примере показан оператор вычитания, используемый вначале как унарный оператор, а затем как бинарный.
trace(-3); // -3 trace(7 - 2); // 5
77
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Старшинство и ассоциативность операторов
Старшинство и ассоциативность операторов определяют порядок, в котором обрабатываются операторы. Хотя может показаться абсолютно естественным для всех, кто знаком с арифметическими операциями, что компилятор должен обрабатывать оператор умножения (
*
) перед оператором сложения (
+
), в действительности компилятору необходимо явное указание того, какие операторы обрабатывать в первую очередь. Такие инструкции обычно упоминаются как старшинство операторов. ActionScript определяет старшинство операторов по умолчанию, которое можно изменить с помощью оператора скобки (
()
). Например, в следующем программном коде изменяется заданное по умолчанию старшинство операторов из предыдущего примера, чтобы заставить компилятор обработать оператор сложения перед оператором умножения.
var sumNumber:uint = (2 + 3) * 4; // uint == 20
Могут возникнуть ситуации, в которых в одном выражении встретятся два или большее число операторов одного старшинства. В таких случаях компилятор использует правила ассоциативности, чтобы определить, какой оператор обрабатывать в первую очередь. Все бинарные операторы, за исключением оператора присваивания, являются ассоциируемыми слева , а это значит, что операторы слева обрабатываются раньше, чем операторы справа. Операторы присваивания и оператор условия (
?:
) являются ассоциируемыми справа операторами, и это означает, что операторы справа обрабатываются раньше, чем операторы слева.
Например, рассмотрим операторы меньше (
<
) и больше (
>
), имеющие одинаковое старшинство. Если оба оператора используются в одном выражении, оператор слева обрабатывается раньше, поскольку оба оператора являются ассоциируемыми слева. Это означает, что результат выполнения следующих двух инструкций будет одинаков.
trace(3 > 2 < 1); // false trace((3 > 2) < 1); // false
Оператор «больше» обрабатывается в первую очередь, что приводит к итоговому значению true
, поскольку операнд 3 больше, чем операнд 2. Значение true
затем передается оператору «меньше» вместе с операндом 1. В следующем программном коде показано промежуточное состояние. trace((true) < 1); Оператор «меньше» преобразует значение true
в цифровое значение 1 и сравнивает это числовое значение со вторым операндом 1, возвращая значение false
(значение 1 не меньше значения 1).
trace(1 < 1); // false
Заданную по умолчанию ассоциативность слева можно изменить с помощью оператора скобки. Можно заставить компилятор обрабатывать оператор «меньше» первым, если заключить этот оператор и его операнды в скобки. В следующем примере используется оператор скобки, чтобы получить другой результат, взяв в качестве операндов числа из предыдущего примера.
trace(3 > (2 < 1)); // true
Оператор «меньше» обрабатывается в первую очередь, что приводит к итоговому значению false
, поскольку операнд 2 не меньше, чем операнд 1. Значение false
затем передается оператору «больше» вместе с операндом 3. В следующем программном коде показано промежуточное состояние. trace(3 > (false)); Оператор «больше» преобразует значение false
в числовое значение 0 и сравнивает это числовое значение с операндом 3, возвращая значение true
(значение 3 больше, чем 0).
trace(3 > 0); // true
78
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
В следующей таблице приведен список операторов ActionScript 3.0 в порядке уменьшения их старшинства. Каждая строка таблицы содержит операторы одинакового старшинства. Каждая строка операторов имеет более высокое старшинство, чем строка, отображающаяся ниже в таблице.
Основные операторы В число основных операторов входят те операторы, которые используются для создания литералов Array и Object, выражений группирования, функций вызова, инициации экземпляров классов, а также доступа к свойствам. Все основные операторы, как показано в следующей таблице, имеют одинаковое старшинство. Операторы, являющиеся частью спецификации E4X, показаны с условным знаком (E4X).
Группа Операторы
Основные
[] {x:y} () f(x) new x.y x[y] <></> @ :: ..
Постфиксные
x++ x--
Унарные
++x --x + - ~ ! delete typeof void
Мультипликативные
* / %
Аддитивные
+ -
Побитовая сдвижка
<< >> >>>
Реляционные
< > <= >= as in instanceof is
Равенство
== != === !==
Побитовое AND
&
Побитовое XOR
^
Побитовое OR
|
Логическое AND
&&
Логическое OR
||
Условие ?:
Присваивание
= *= /= %= += -= <<= >>= >>>= &= ^= |=
Запятая
,
Оператор Выполняемая операция
[]
Инициализируется массив
{x:y}
Инициализируется объект
()
Группируются выражения
f(x)
Выполняется вызов функции
new
Выполняется вызов конструктора
x.y x[y]
Выполняется доступ к свойству
<></>
Инициализируется объект XMLList (E4X)
79
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Постфиксные операторы Постфиксные операторы берут какой-либо оператор и либо инкрементально увеличивают, либо декрементально уменьшают его значение. Хотя эти операторы и являются унарными, они классифицируются отдельно от остальных унарных операторов из-за своего высокого старшинства и особого поведения. Если постфиксный оператор используется как часть более крупного выражения, значение выражения возвращается до обработки этого оператора. Например, в следующем программном коде показано, что значение выражение xNum++
возвращается до того, как значение инкрементально увеличивается.
var xNum:Number = 0; trace(xNum++); // 0 trace(xNum); // 1
Все постфиксные операторы, как показано в следующей таблице, имеют одинаковое старшинство.
Унитарные операторы Унитарные операторы получают один операнд. Операторы инкрементального увеличения (
++
) и декрементального уменьшения (
--
) в этой группе являются префикснымиоператорами, и это означает, что они могут появляться перед операндами в выражении. Префиксные операторы отличаются от своих постфиксных эквивалентов тем, что операции инкрементального увеличения и декрементального уменьшения выполняются перед возвращением значения всего выражения. Например, в следующем программном коде показано, что значение выражение ++xNum
возвращается до того, как значение инкрементально увеличивается.
var xNum:Number = 0; trace(++xNum); // 1 trace(xNum); // 1
Все унарные операторы, как показано в следующей таблице, имеют одинаковое старшинство.
@
Выполняется доступ к атрибуту (E4X)
::
Уточняется имя (E4X)
..
Выполняется доступ к производному XML-элементу (E4X)
Оператор Выполняемая операция
++
Инкрементально увеличивает (постфиксный)
--
Декрементально уменьшает (постфиксный)
Оператор Выполняемая операция
++
Инкрементально увеличивает (префиксный)
--
Декрементально уменьшает (префиксный)
+
Унарный +
-
Унарный — (отрицание)
!
Логическое NOT
~
Побитовое NOT
Оператор Выполняемая операция
80
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Мультипликативные операторы Мультипликативные операторы получают два операнда и выполняют умножение, деление или вычисление модуля.
Все мультипликативные операторы, как показано в следующей таблице, имеют одинаковое старшинство.
Аддитивные операторы
Аддитивные операторы получают два операнда и выполняют операции сложения или вычитания. Все аддитивные операторы, как показано в следующей таблице, имеют одинаковое старшинство.
Операторы побитового сдвига Операторы побитового сдвига получают два операнда и сдвигают биты первого операнда на величину, указанную во втором операнде. Все операторы побитового сдвига, как показано в следующей таблице, имеют одинаковое старшинство. Реляционные операторы
Реляционные операторы получают два операнда, сравнивают их значения, а затем возвращают логическое значение (Boolean). Все реляционные операторы, как показано в следующей таблице, имеют одинаковое старшинство.
delete
Свойство удаляется
typeof
Возвращается информация о типе
void
Возвращается значение undefined
Оператор Выполняемая операция
*
Умножение
/
Деление
%
Вычисление модуля
Оператор Выполняемая операция
+
Сложение
-
Вычитание
Оператор Выполняемая операция
<<
Побитовый сдвиг влево
>>
Побитовый сдвиг вправо
>>>
Побитовый сдвиг вправо без знака
Оператор Выполняемая операция
81
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Операторы равенства Операторы равенства получают два операнда, сравнивают их значения, а затем возвращают логическое значение (Boolean). Все операторы равенства, как показано в следующей таблице, имеют одинаковое старшинство.
Побитовые логические операторы Побитовые логические операторы получают два операнда и выполняют логические операции на битовом уровне. Побитовые логические операторы отличаются по старшинству и перечислены в следующей таблице в порядке убывания старшинства.
Логические операторы Логические операторы получают два операнда и возвращают логическое значение (Boolean). Логические операторы отличаются по старшинству и перечислены в следующей таблице в порядке убывания старшинства.
Оператор Выполняемая операция
<
Меньше
>
Больше
<=
Меньше или равно
>=
Больше или равно
as
Проверяется тип данных
in
Проверяются свойства объекта
instanceof
Проверяется цепочка прототипа
is
Проверяется тип данных
Оператор Выполняемая операция
==
Равенство
!=
Неравенство
===
Строгое равенство
!==
Строгое неравенство
Оператор Выполняемая операция
&
Побитовое AND
^
Побитовое XOR
|
Побитовое OR
Оператор Выполняемая операция
&&
Логическое AND
||
Логическое OR
82
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Оператор условия
Оператор условия является тернарным оператором, и это значит, что ему передается три операнда. Оператор условия — это экспресс-метод применения инструкции условного выбора if..else .
Операторы присваивания
Операторы присваивания получают два оператора и присваивают значение одному оператору на основе значения другого оператора. Все операторы присваивания, как показано в следующей таблице, имеют одинаковое старшинство.
Условия
ActionScript 3.0 обеспечивает три основных инструкции условия, которые можно использовать для управления программным потоком.
инструкция if..else
Инструкция условия if..else
позволяет проверить условие и выполнить блок программного кода, если это условие соблюдено, либо выполнить другой программный код, если условие нарушено. Например, в следующем программном коде проверяется, превышает ли x
значение 20, создается функция trace()
, если условие выполняется, или создается другая функция trace()
, если это не так.
Оператор Выполняемая операция
?:
Условие
Оператор Выполняемая операция
=
Присваивание
*=
Присваивание умножения
/=
Присваивание удаление
%=
Присваивание модуля
+=
Присваивание сложения
-=
Присваивание вычитания
<<=
Присваивание побитового сдвига влево
>>=
Присваивание побитового сдвига вправо
>>>=
Присваивание побитового сдвига вправо без знака
&=
Присваивание побитового AND
^=
Присваивание побитового XOR
|=
Присваивание побитового OR
83
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
if (x > 20) { trace("x is > 20"); } else { trace("x is <= 20"); }
Если не требуется выполнять альтернативный блок программного кода, можно использовать инструкцию if
без инструкции else
.
инструкция if..else if
Можно проверить больше одного условия, используя инструкцию условия if..else if
. Например, в следующем программном коде не только проверяется, превышает ли x
значение 20, но также проверяется, не является ли значение x
отрицательным.
if (x > 20) { trace("x is > 20"); } else if (x < 0) { trace("x is negative"); }
Если за инструкцией if
или else
следует только одна инструкция, эту инструкцию необязательно включать в скобки. Например, в следующем программном коде скобки не используются.
if (x > 0) trace("x is positive"); else if (x < 0) trace("x is negative"); else trace("x is 0");
Однако корпорация Adobe рекомендует, чтобы всегда использовались скобки, поскольку, если в дальнейшем к инструкции условия без скобок добавится дополнительное условие, возможно неожиданное поведение программного кода. Например, в следующем программном коде значение positiveNums
увеличивается на 1 независимо от того, получается ли в результате проверки условия значение true
или нет.
var x:int; var positiveNums:int = 0; if (x > 0) trace("x is positive"); positiveNums++; trace(positiveNums); // 1
84
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
switch
Инструкция switch
полезна, если имеется несколько путей выполнения, которые зависят от одного выражения условия. При этом обеспечивается функциональность, сходная с несколькими последовательными инструкциями if..else if
, но несколько более удобочитаемая. Вместо проверки условия для логического значения инструкция switch
оценивает выражение и использует результат для определения того, какой блок программного кода следует выполнять. Блоки кода начинаются инструкциями case
и заканчиваются инструкциями break
. Например, в следующей инструкции switch
печатается день недели, на основе номера дня, возвращаемого методом Date.getDay()
.
var someDate:Date = new Date(); var dayNum:uint = someDate.getDay(); switch(dayNum) { case 0: trace("Sunday"); break; case 1: trace("Monday"); break; case 2: trace("Tuesday"); break; case 3: trace("Wednesday"); break; case 4: trace("Thursday"); break; case 5: trace("Friday"); break; case 6: trace("Saturday"); break; default: trace("Out of range"); break; }
Повтор
Инструкции цикла позволяют повторно выполнить определенный блок программного кода, используя несколько значений переменных. Корпорация Adobe рекомендует, чтобы блок кода всегда включался в кавычки (
{}
). Хотя можно пропустить скобки, если блок кода содержит всего одну инструкцию, на практике так делать не рекомендуется по той же причине, почему не рекомендуется и для условий: увеличивается вероятность непреднамеренного исключения инструкции из блока кода в случае их последующего добавления. Если впоследствии добавится инструкция, которую нужно включить в блок кода, но при этом будут забыты обязательные скобки, инструкция не будет выполняться как часть цикла.
85
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
for
Инструкция цикла for
позволяет итеративно увеличивать переменную в определенном диапазоне значений. Необходимо передать в инструкцию for
три выражения: переменную, установленную в качестве исходного значения; инструкцию условия, определяющую окончание цикла; а также выражение, которое изменяет значение переменной для каждого цикла. Например, в следующем программном коде цикл выполняется пять раз. Значение переменной i
начинается с 0 и заканчивается 4, выходным значением будут числа от 0 до 4, каждое в своей строке.
var i:int; for (i = 0; i < 5; i++) { trace(i); }
for..in
Инструкция цикла for..in
выполняет итерации для свойства объекта или элементов массива. Например, можно использовать инструкцию цикла for..in
для выполнения итераций со значениями свойства родового объекта (свойства объекта не сохраняются в определенном порядке, поэтому свойства могут появляться в кажущемся произвольном порядке).
var myObj:Object = {x:20, y:30}; for (var i:String in myObj) { trace(i + ": " + myObj[i]); } // output: // x: 20 // y: 30
Также можно выполнять итерацию по элементам массива.
var myArray:Array = ["one", "two", "three"]; for (var i:String in myArray) { trace(myArray[i]); } // output: // one // two // three
Чего нельзя делать, так это выполнять итерацию по свойствам объекта, если он является экземпляром определенного пользователем класса, если этот класс не является динамическим классом. Но даже с экземпляром динамического класса можно выполнять итерации только по свойствам, которые добавляются динамически.
for each..in
Инструкция цикла for each..in
выполняет итерации по элементам коллекции, которые могут быть либо тэгами в объекте XML или XMLList, либо значениям, содержащимся в свойствах объекта, а также элементами массива. Например, как показывает следующая выборка, можно использовать цикл for each..in
для итерации по свойствам родового объекта, но в отличие от цикла for..in
, переменная-итератор в цикле for each..in
содержит значение свойства вместо имени свойства.
86
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
var myObj:Object = {x:20, y:30}; for each (var num in myObj) { trace(num); } // output: // 20 // 30
Можно выполнять итерации по объектам XML или XMLList, как показано в следующем примере.
var myXML:XML = <users> <fname>Jane</fname> <fname>Susan</fname> <fname>John</fname> </users>; for each (var item in myXML.fname) { trace(item); } /* output Jane Susan John */
Также можно выполнять итерации по элементам массива, как в следующем примере.
var myArray:Array = ["one", "two", "three"]; for each (var item in myArray) { trace(item); } // output: // one // two // three
Нельзя выполнять итерацию по свойствам объекта, если он является экземпляром запечатанного класса. Даже для экземпляров динамических классов нельзя выполнять итерации по каким-либо фиксированным свойствам, какими являются свойства, определенные как часть определения класса.
while
Цикл while
работает аналогично инструкции if
, выполняя повторения до тех пор, пока для условия выдается значение true
. Например, в следующем программном коде получаются такие же результаты, что и в примере с циклом for
.
var i:int = 0; while (i < 5) { trace(i); i++; }
87
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Одним из недостатков использования цикла while
вместо цикла for
является то, что неопределенные циклы проще писать с помощью циклов while
. Пример программного кода с циклом for
не компилируется, если пропущено выражение, которое инкрементально увеличивает переменную обратного счетчика, но цикл while
не компилируется, если пропущен этот шаг. Без выражения, инкрементально увеличивающего переменную i
, цикл становится неопределенным циклом.
do..while
Цикл do..while
является циклом while
, в котором гарантируется, что блок кода будет выполнен хотя бы один раз, поскольку условие проверяется после выполнения блока программного кода. В следующем программном коде показан простой пример цикла do..while
, создающего выходные данные даже в случае несоблюдения условия.
var i:int = 5; do { trace(i); i++; } while (i < 5); // output: 5
Функции
Функциями называют блоки программного кода, выполняющие определенные задачи, которые можно повторно использовать в программах. В ActionScript 3.0 существует два типа функций: методы и закрытия функций. То, называется ли функция методом или закрытием функции, зависит от контекста, в котором определена эта функция. Функция называется методом, если она определяется как часть определения класса или прикрепляется к экземпляру объекта. Функция называется закрытием функции, если она определена каким-либо другим способом. Функции всегда были очень важны в ActionScript. В ActionScript 1.0, например, ключевое слово class
отсутствует, поэтому «классы» определялись функциями конструктора. Хотя ключевое слово class
с тех пор и было добавлено к языку, четкое понимание функций по-прежнему важно, если требуется полностью использовать все преимущества, предлагаемые языком. Это, возможно, вызовет сложности у программистов, ожидающих, что функции ActionScript будут вести себя так же, как функции в языке C++ или Java. Хотя само определение основной функции и ее вызовов не должно представлять сложности для опытных программистов, некоторые более сложные возможности функций ActionScript требуют дополнительного объяснения.
Концепции основной функции
В этом разделе обсуждается определение основной функции и технологий ее вызова.
Вызов функций
При вызове функции с помощью ее идентификатора с указанием последующего оператора скобки (
()
). Оператор скобки используется для включения любых функциональных параметров, которые требуется передать функции. Например, функция trace()
, которая является функцией верхнего уровня в ActionScript 3.0, широко используется в этой книге:
trace("Use trace to help debug your script");
88
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Если вызывается функция без параметров, необходимо использовать пустые парные скобки. Например, можно использовать метод Math.random()
, который не получает параметров, чтобы создавать произвольные числа.
var randomNum:Number = Math.random();
Определение собственных функций
В ActionScript 3.0 существует два способа определить функцию: можно использовать инструкцию function или выражение function. Выбираемая технология зависит от того, какой стиль программирования предпочтительнее: статический или динамический. Определите собственные функции с помощью инструкции function, если предпочтителен статический или строгий режим программирования. Определяйте свои функции с помощью выражения function, если в этом есть особая необходимость. Выражение function более часто используется в динамическом программировании или при использовании стандартного режима.
Инструкции Function
Инструкции Function являются предпочтительной методикой для определения функций в строгом режиме. Инструкция function начинается с ключевого слова function
, за которым идут следующие элементы.
•
Имя функции
•
Список параметров, разделенных запятыми, заключенный в скобки
•
Тело функции — это программный код ActionScript, который будет выполняться при вызове функции, заключенный в фигурные скобки
Например, в следующем программном коде создается функция, определяющая параметр, а затем выполняется вызов этой функции с использованием строки "hello"
в качестве значения параметра.
function traceParameter(aParam:String) { trace(aParam); } traceParameter("hello"); // hello
Выражения Function
Другим способом объявить функцию можно, используя инструкцию присваивания с выражением function. Этот метод иногда называется литералом функции или анонимной функцией. Это более трудоемкий метод, который широко использовался в ранних версиях ActionScript. Инструкция присваивания с выражением функции начинается с ключевого слова var
, за которым идут следующие элементы.
•
Имя функции
•
Оператор двоеточие (
:
)
•
Класс Function
для указания типа данных
•
Оператор присваивания (
=
)
•
Ключевое слово function
•
Список параметров, разделенных запятыми, заключенный в скобки
•
Тело функции — это программный код ActionScript, который будет выполняться при вызове функции, заключенный в фигурные скобки
89
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Например, в следующем программном коде объявляется функция traceParameter
, использующая выражение function.
var traceParameter:Function = function (aParam:String) { trace(aParam); }; traceParameter("hello"); // hello
Обратите внимание, что в отличие от инструкции function имя функции не указывается. Другим важным отличием между выражениями function и инструкциями function является то, что выражение это именно выражение, а не инструкция. Это означает, что выражение function не может использоваться отдельно, подобно инструкции function. Выражение function может использоваться только в качестве части инструкции, обычно инструкции присваивания. В следующем примере показано выражение function, присвоенное элементу массива.
var traceArray:Array = new Array(); traceArray[0] = function (aParam:String) { trace(aParam); }; traceArray[0]("hello");
Выбор между инструкцией и выражением
Стандартное правило предписывает использовать инструкцию function до тех пор, пока в силу особых обстоятельств не потребуется использовать выражение. Инструкции function менее трудоемки и обеспечивают более согласованную работу в строгом и стандартном режиме, чем выражения function. Инструкции function проще читаются чем инструкции присваивания, содержащие выражения function. Инструкции function делают код более кратким; они вносят меньше путаницы, чем выражения function, для которых требуется использовать оба ключевых слова: var
и function
. Инструкции function обеспечивают более согласованное поведение в обоих режимах компилятора, поскольку для вызова метода, объявленного с помощью инструкции function, можно использовать синтаксис с точкой как в строгом, так и в стандартном режимах. Это не обязательно так для методов, объявленных с помощью выражения function. Например, в следующем программном коде определяется класс с именем Example, содержащий два метода: methodExpression()
, объявляемый с помощью выражения function, а также метод methodStatement()
, объявляемый с помощью инструкции function. В строгом режиме нельзя использовать синтаксис с точкой для вызова метода methodExpression()
.
class Example { var methodExpression = function() {} function methodStatement() {} } var myEx:Example = new Example(); myEx.methodExpression(); // error in strict mode; okay in standard mode myEx.methodStatement(); // okay in strict and standard modes
Считается, что выражения function лучше подходят для программирования, в котором больше внимания уделяется поведению во время выполнения или динамическому поведению. Если предпочтительно использовать строгий режим, но также необходимо вызывать метод, объявленный с помощью выражения function, можно использовать одну из двух технологий. Во-первых, можно вызвать метод, используя квадратные скобки (
[]
) вместо оператора точки (
.
). Вызов следующего метода успешно выполняется как в строгом, так и в стандартном режимах.
90
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
myExample["methodLiteral"]();
Во-вторых, можно объявить весь класс динамическим. Хотя это позволит вызывать метод с помощью оператора точки, с другой стороны придется пожертвовать возможностью работы в строгом режиме со всеми экземплярами данного класса. Например, что компилятор не создает ошибку при попытке доступа к неопределенному свойству экземпляра динамического класса. В некоторых обстоятельствах выражения могут быть очень полезны. Одним из наиболее распространенных случаев применения выражений function являются функции, которые используются однократно и потом сбрасываются. Другим менее частым вариантом применения является присоединение функции к свойству прототипа. Дополнительные сведения см. в разделе «Объект прототипа» на странице 131.
Существует два тонких различия между инструкциями function и выражениями function, которые следует учитывать при выборе методики использования. Первое отличие состоит в том, что выражения function не существуют независимо как объекты в отношении управления памятью и освобождения ресурсов. Говоря другими словами, если выражение function присваивается другому объекту, такому как элемент массива или свойство объекта, создается только ссылка на это выражение function в программном коде. Если этот элемент массива или объект, к которому прикрепляется выражение function, выходит из области действия или, говоря другими словами, больше недоступен, доступ к этому выражению function прекращается. Если этот элемент массива или объект удаляются, память, использовавшая выражение function, становится доступной для освобождения ресурсов, и это значит, что данную память могут затребовать и повторно использовать для других целей.
В следующем примере показано, что в выражении function, как только свойство, к которому присвоено выражение, удаляется, функция перестает быть доступной. Класс Test является динамическим, что означает, что можно добавить свойство с именем functionExp
, в котором содержится выражение функции. Функции functionExp()
могут вызываться с помощью оператора точка, но как только свойство functionExp
удаляется, функция перестает быть доступной.
dynamic class Test {} var myTest:Test = new Test(); // function expression myTest.functionExp = function () { trace("Function expression") }; myTest.functionExp(); // Function expression delete myTest.functionExp; myTest.functionExp(); // error
Но, с другой стороны, если функция в начале определяется с помощью инструкции function, то она существует как независимый объект и продолжает существовать даже после удаления свойства, к которому она прикреплена. Оператор delete
работает только со свойствами объектов, поэтому даже запрос на удаление самой функции stateFunc()
не срабатывает.
dynamic class Test {} var myTest:Test = new Test(); // function statement function stateFunc() { trace("Function statement") } myTest.statement = stateFunc; myTest.statement(); // Function statement delete myTest.statement; delete stateFunc; // no effect stateFunc();// Function statement myTest.statement(); // error
91
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Второе различие между инструкциями function и выражениями function состоит в том, что инструкции function существуют во всей области действия, для которой они определены, в том числе и для инструкций, предшествовавших инструкции function. Выражения function, в отличие от этого, определяются только для последующих инструкций. Например, в следующем программном коде функция scopeTest()
успешно вызывается до того, как она была определена.
statementTest(); // statementTest function statementTest():void { trace("statementTest"); }
Выражения function недоступны до тех пор, пока они не определены, поэтому возникает ошибка при выполнении следующего программного кода.
expressionTest(); // run-time error var expressionTest:Function = function () { trace("expressionTest"); }
Возвращение значений из функций
Чтобы возвратить значение из функции, используйте инструкцию return
с последующим указанием значения выражения или литерала, которое требуется вернуть. Например, в следующем программном коде возвращается выражение, отображающее этот параметр. function doubleNum(baseNum:int):int { return (baseNum * 2); }
Обратите внимание, что инструкция return
прерывает выполнение функции, поэтому любые инструкции, следующие за инструкцией return
, выполняться не будут, как показано далее.
function doubleNum(baseNum:int):int { return (baseNum * 2); trace("after return"); // This trace statement will not be executed. }
В строгом режиме необходимо, чтобы возвращалось значение соответствующего типа, если указан тип возвращаемого значения. Например, следующий программный код создает ошибку в строгом режиме, поскольку не возвращает действительное значение.
function doubleNum(baseNum:int):int { trace("after return"); }
Вложенные функции
Можно выполнять вложение функций, это означает, что функции могут быть объявлены с другими функциями. Вложенная функция доступна только в рамках родительской функции до тех пор, пока ссылки на эту функцию передаются во внешний программный код. Например, в следующем программном коде объявляется две вложенных функции внутри функции getNameAndVersion()
.
92
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
function getNameAndVersion():String { function getVersion():String { return "10"; } function getProductName():String { return "Flash Player"; } return (getProductName() + " " + getVersion()); } trace(getNameAndVersion()); // Flash Player 10
Если вложенные функции передаются во внешний программный код, они предаются как закрытия функций, и это означает, что функция сохраняет все определения, бывшие в области действия во время ее определения. Дополнительные сведения см. в разделе «Область действия функции» на странице 97.
Параметры функций
ActionScript 3.0 обеспечивает определенную функциональность для параметров функций, которые могут показаться нестандартными для программистов, мало знакомых с этим языком. Хотя идея передачи параметров значением или ссылкой должна быть знакома большинству программистов, объект arguments
и параметр ... (rest) многим еще не знакомы.
Передача аргументов значением и ссылкой
Во многих языках программирования очень важно понимать различие между передачей аргументов значением или ссылкой; это различие может влиять на способ разработки программного кода. Передача значением подразумевает, что значение аргумента копируется в локальную переменную для использования внутри функции. Передача ссылкой означает, что вместо фактического значения передается только ссылка на аргумент. Копирование фактического значения аргумента не выполняется. Вместо этого передается ссылка на переменную, поскольку аргумент создается и присваивается локальной переменной для использования внутри функции. Так как ссылка на переменную находится вне функции, локальная переменная дает возможность изменять значение исходной переменной.
В ActionScript 3.0 все аргументы передаются ссылками, поскольку все значения хранятся как объекты. Однако объекты, принадлежащие примитивным типам данных, к которым относятся Boolean, Number, int, uint, и String, имеют специальные операторы, которые позволяют воспроизвести поведение объектов при передаче аргументов значениями. Например, в следующем программном коде создается функция с именем passPrimitives()
, определяющая два параметра с именем xParam
и yParam
, оба с типом int. Эти параметры сходны с локальными переменными, объявленными в теле функции passPrimitives()
. Если функция вызывается с аргументами xValue
и yValue
, параметры xParam
и yParam
инициализируются со ссылками на объекты int, представленные значениями xValue
и yValue
. Поскольку эти аргументы имеют примитивные типы, они ведут себя так, как если бы передавались значениями. Хотя параметры xParam
и yParam
изначально содержат только ссылки на xValue
и yValue
объекты, любые изменения переменных в теле функции создают новые копии значений в памяти.
93
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
function passPrimitives(xParam:int, yParam:int):void { xParam++; yParam++; trace(xParam, yParam); } var xValue:int = 10; var yValue:int = 15; trace(xValue, yValue);// 10 15 passPrimitives(xValue, yValue); // 11 16 trace(xValue, yValue);// 10 15
В функции passPrimitives()
значения xParam
и yParam
являются инкрементальными, но это не влияет на значения xValue
и yValue
, как показано в последней инструкции trace
. И это действительно будет так, даже если параметры будут названы так же, как переменные, xValue
и yValue
, поскольку имена xValue
и yValue
внутри функции будут указывать на новое местоположение в памяти, которое существует отдельно от переменных с таким же именем вне функции.
Все другие объекты, т.е объекты, которые не принадлежат примитивным типам данных, всегда передаются ссылками, что дает возможность изменять значение исходной переменной. Например, в следующем программном коде создается объект с именем objVar
и двумя свойствами: x
и y
. Этот объект передается как аргумент функции passByRef()
. Поскольку тип данных объекта не примитивный, он не только предается ссылкой, но также хранится как ссылка. Это означает, что изменения, вносимые в параметры в функции, будут влиять на свойства объекта вне функции.
function passByRef(objParam:Object):void { objParam.x++; objParam.y++; trace(objParam.x, objParam.y); } var objVar:Object = {x:10, y:15}; trace(objVar.x, objVar.y); // 10 15 passByRef(objVar); // 11 16 trace(objVar.x, objVar.y); // 11 16
Параметр objParam
ссылается на тот же объект, что и глобальная переменная objVar
. Как можно видеть из инструкции trace
в приведенном примере, изменения свойств x
и y
в объекте objParam
отражаются в объекте objVar
.
Значения параметров по умолчанию
Новой возможностью ActionScript 3.0 является способность объявлять для функции значения параметров по умолчанию. Если вызывается функция со значениями параметров по умолчанию, используются значения, указанные для параметров в определении функции. Все параметры со значениями по умолчанию должны быть помещены в конец списка параметров. Значения, которые присвоены в качестве значений по умолчанию должны быть константами, определяемыми во время компиляции. Существование для параметра значения по умолчанию фактически делает этот параметр необязательным параметром. Параметр без значения по умолчанию считается обязательным параметром.
Например, в следующем программном коде создается функция с тремя параметрами, два из которых имеют значения по умолчанию. При вызове этой функции только с одним параметром используются значения для параметров по умолчанию. 94
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
function defaultValues(x:int, y:int = 3, z:int = 5):void { trace(x, y, z); } defaultValues(1); // 1 3 5
Объект arguments
Если параметры передаются в функцию, можно использовать объект arguments
для доступа к информации о параметрах, переданных функции. Наиболее важными для объекта arguments
являются следующие аспекты.
•
Объект arguments
является массивом, содержащим все параметры, переданные функции.
•
Свойство arguments.length
сообщает о числе параметров, переданных функции.
•
Свойство arguments.callee
передает ссылку на саму функцию, которая очень полезна при рекурсивных вызовах выражений function.
Примечание. Объект arguments
недоступен, если какой-либо параметр имеет имя arguments
, а также в тех случаях, когда используется параметр ... (rest).
Если в теле функции есть ссылки на объект arguments
, ActionScript 3.0 позволяет включать в вызов функции больше параметров, чем указано в определении функции. Однако в строгом режиме будет выдаваться ошибка компиляции, если число переданных параметров не соответствует числу обязательных параметров (и дополнительных параметров, если такие имеются). Можно использовать этот аспект массива в объекте arguments
для доступа к любому параметру, переданному функции, без учета того, был ли этот параметр задан в определении функции или нет. В следующем примере, который компилируется только в стандартном режиме, массив arguments
со свойством arguments.length
используется для отслеживания всех параметров, переданных в функцию traceArgArray()
.
function traceArgArray(x:int):void { for (var i:uint = 0; i < arguments.length; i++) { trace(arguments[i]); } } traceArgArray(1, 2, 3); // output: // 1 // 2 // 3
Свойство arguments.callee
часто используется в анонимных функциях для выполнения рекурсии. С ее помощью можно добавить гибкости создаваемому программному коду. Если имя рекурсивной функции изменяется в ходе цикла разработки, не следует беспокоиться об изменении рекурсивных вызовов в теле функции, если вместо имени функции используется свойство arguments.callee
. Свойство arguments.callee
используется в следующем выражении function для разрешения рекурсии.
95
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
var factorial:Function = function (x:uint) { if(x == 0) { return 1; } else { return (x * arguments.callee(x - 1)); } } trace(factorial(5)); // 120
Если при объявлении функции используется параметр ... (rest), объект arguments
будет недоступен. Вместо него необходимо будет обращаться к параметрам, используя объявленные для них имена. Необходимо быть аккуратным, чтобы избежать использование строки "arguments" в качестве имени параметра, поскольку это сделает недоступным объект arguments
. Например, если функция traceArgArray()
перезаписывается, так что добавляется параметр arguments
, ссылка arguments
в теле функции будет вызывать обращение параметру, а не к объекту arguments
. В следующем программном коде не создается значений на выходе.
function traceArgArray(x:int, arguments:int):void { for (var i:uint = 0; i < arguments.length; i++) { trace(arguments[i]); } } traceArgArray(1, 2, 3); // no output
Объект arguments
в предыдущих версиях ActionScript также содержал свойство с именем caller
, которое является ссылкой на функцию, вызывающую текущую функцию. Свойство caller
отсутствует в ActionScript 3.0, но если нужна ссылка на вызывающую функцию, можно изменить ее так, чтобы она передавала дополнительный параметр, являющейся ссылкой на нее саму.
Параметр ... (rest)
В ActionScript 3.0 появилось новая возможность объявления параметров, называемая параметр ... (rest). Этот параметр позволяет указать параметр массива, который принимает любые численные, разделенные запятыми аргументы. Этот параметр может иметь любое имя, при условии, что оно не является зарезервированным словом. Это объявление параметра должно быть последним указываемым параметром. Использование этого параметра делает объект arguments
недоступным. Хотя параметр ... (rest) дает ту же функциональность, что и массив arguments
и свойство arguments.length
, он не обеспечивает возможностей свойства arguments.callee
. Необходимо убедиться, что использование возможностей свойства arguments.callee
действительно не требуется, прежде чем использовать параметр ... (rest).
В следующем примере функция traceArgArray()
перезаписывается с использованием параметра ... (rest) вместо объекта arguments
.
96
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
function traceArgArray(... args):void { for (var i:uint = 0; i < args.length; i++) { trace(args[i]); } } traceArgArray(1, 2, 3); // output: // 1 // 2 // 3
Параметр ... (rest) также может использоваться с другими параметрами, с условием, что он будет последним параметром в списке. В следующем примере функция traceArgArray()
изменяется таким образом, что ее первый параметр, x
, становится типом int, а второй — использует параметр ... (rest). При выводе первое значение пропускается, поскольку первый параметр больше не является частью массива, созданного параметром ... (rest).
function traceArgArray(x: int, ... args) { for (var i:uint = 0; i < args.length; i++) { trace(args[i]); } } traceArgArray(1, 2, 3); // output: // 2 // 3
Функции в качестве объектов
В ActionScript 3.0 функции являются объектами. При создании функции создается объект, который не только может передаваться как параметр другой функции, но также имеет свойства и методы, прикрепленные к нему.
Функции передаются как аргументы другим функциям в виде ссылок, а не значений. Если функция передается как аргумент, используется только ее идентификатор, но не оператор скобки, применяемый для вызова метода. Например, в следующем программном коде функция с именем clickListener()
передается как аргумент методу addEventListener()
.
addEventListener(MouseEvent.CLICK, clickListener);
Метод Array.sort()
также определяет параметр, принимающий функцию. В качестве примера пользовательской функции сортировки, используемой как аргумент для функции Array.sort()
см. «Сортировка массива» на странице 175.
97
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Хотя это может показаться странным для программистов, которые только начинают изучать ActionScript, как и любой другой объект, функции могут иметь свойства и методы. Действительно, каждая функция обладает доступным только для чтения свойством с именем length
, в котором храниться число параметров, определенное для функции. Это свойство отличается от свойства arguments.length
, в котором сообщалось о числе аргументов, переданных функции. Вспомним, что в ActionScript число аргументов, переданных функции, может превышать число параметров, заданных в определении этой функции. В следующем примере, который компилируется только в стандартном режиме, поскольку для строгого режима требуется точное соответствие числа переданных аргументов и параметров в определении, показано различие между этими двумя свойствами.
// Compiles only in standard mode function traceLength(x:uint, y:uint):void { trace("arguments received: " + arguments.length); trace("arguments expected: " + traceLength.length); } traceLength(3, 5, 7, 11); /* output: arguments received: 4 arguments expected: 2 */
В стандартном режиме можно определить свои собственные свойства функции, поместив их определение вне тела создаваемой функции. Свойства функции могут выступать в роли квази-статических свойств, позволяя сохранять состояние переменной, связанной с данной функцией. Например, возможно, потребуется отследить, сколько раз вызывается определенная функция. Такая возможность может быть полезна, если пишется игра и требуется отследить, сколько раз пользователь применял определенную команду, хотя для этой цели вполне можно использовать и свойство статического класса. В следующем примере, компилируемом только в стандартном режиме, поскольку строгий режим не допускает добавления динамических свойств к функциям, создается свойство функции вне ее определения, а затем это свойство инкрементально увеличивается при каждом вызове функции.
// Compiles only in standard mode var someFunction:Function = function ():void { someFunction.counter++; } someFunction.counter = 0; someFunction(); someFunction(); trace(someFunction.counter); // 2
Область действия функции
Область действия функции определяет не только, где в программе может вызываться функция, но также определения, которые доступны этой функции. Те же правила области действия, которые применимы к идентификаторам переменных, применяются и к идентификаторам функций. Функция, объявленная в глобальной области действия, доступна в любом месте программного кода. Например, ActionScript 3.0 содержит глобальные функции, такие как isNaN()
и parseInt()
, которые доступны в любом месте программного кода. Вложенная — это функция, объявленная внутри другой функции, которая может использоваться в любом месте функции, внутри которой она объявлена.
98
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Язык ActionScript и его синтаксис
Цепочка области действия
Всякий раз, когда начинается выполнение функции, создается ряд объектов и свойств. Во-первых, создается специальный объект с названием объект активации, который хранит параметры и все локальные переменные или функции, объявленные в теле данной функции. Напрямую обратиться к объекту активации нельзя, поскольку это внутренний механизм. Во-вторых, создается цепочка области действия, содержащая упорядоченный список объектов, для которых Flash Player или Adobe AIR проверяют объявления идентификаторов. Каждая выполняемая функция имеет цепочку области действия, хранимую во внутреннем свойстве. Для вложенных функций цепочка области действия начинается с собственного объекта активации, за которым следует объект активации родительской функции. Цепочка продолжается таким же образом, пока не будет достигнут глобальный объект. Глобальный объект создается при запуске программы ActionScript и содержит все глобальные переменные и функции. Закрытия функций
Закрытие функции — это объект, содержащий моментальный снимок функции и ее лексическую среду. Лексическая среда функции включает все ее переменные, свойства, методы и объекты в цепочке области действия функции, а также их значения. Закрытие функции создается при каждом выполнении функции отдельно от объекта или класса. Тот факт, что закрытия функций удерживают области действия, в которых они были определены, дает интересные результаты, если функция передается в качестве аргумента или возвращаемого значения в другую область действия. Например, в следующем программном коде создаются две функции: foo()
, которая возвращает вложенную функцию с именем rectArea()
, рассчитывающую площадь прямоугольника, и функцию bar()
, вызывающую foo()
и сохраняющую возвращаемое закрытие функции в переменной с именем myProduct
. Несмотря на то, что функция bar()
определяет свою собственную локальную переменную x
(со значением 2), если вызывается закрытие функции myProduct()
, она сохраняет переменную x
(со значением 40), определенную в функции foo(). Функция bar()
, таким образом, возвращает значение 160
вместо 8
.
function foo():Function { var x:int = 40; function rectArea(y:int):int // function closure defined { return x * y } return rectArea; } function bar():void { var x:int = 2; var y:int = 4; var myProduct:Function = foo(); trace(myProduct(4)); // function closure called } bar(); // 160
Методы ведут себя сходным образом, они также сохраняют информацию о лексической среде, в которой они были созданы. Эта особенность наиболее заметна, если метод извлекается из своего экземпляра, создавая связанный метод. Главное отличие между закрытием функции и связанным методом состоит в том, что значение ключевого слова this
в связанном методе всегда ссылается на экземпляр, к которому он был первоначально прикреплен, в то время как в закрытии функции значение ключевого слова this
можно изменять. Дополнительные сведения см. в разделе «Методы» на странице 107.
99
Глава 5. Объектно-ориентированное программирование на языке ActionScript
В этой главе описываются элементы ActionScript поддерживающие объектно-ориентированное программирование (ООП). Здесь не приводятся общие принципы ООП, такие как объектный дизайн, абстракция, инкапсуляция, наследование и полиморфизм. В этой главе рассматривается только применение этих принципов к ActionScript 3.0.
Так как ActionScript, прежде всего, является языком программирования, поддержка ООП является необязательной. Это предоставляет программистам гибкость в выборе оптимального подхода для проектов разного спектра и сложности. Для небольших задач можно ограничиться парадигмой процедурного программирования ActionScript. Для более крупных проектов применение принципов ООП позволяет упростить код для понимания, работы и расширения. Основы объектно-ориентированного программирования
Введение в объектно-ориентированное программирование
Объектно-ориентированное программирование (ООП) — это способ организации кода в программе путем его группировки в виде объектов, то есть отдельных элементов, которые включают информацию (значения данных) и функции. Объектно-ориентированный подход к организации программы позволяет группировать определенные фрагменты информации (например, музыкальную информацию, такую как название альбома, название трека или имя исполнителя) вместе с часто используемыми функциями или действиями, связанными с этой информацией (например, «добавить трек в список воспроизведения» или «воспроизвести все песни этого исполнителя»). Эти элементы объединяются в один элемент, так называемый объект (например, «Album» или «MusicTrack»). Возможность связать вместе эти значения и функции дает несколько преимуществ. Например, нужно отслеживать только одну переменную, а не несколько; можно сгруппировать вместе связанные между собой функции; можно организовать структуру программы так, чтобы она больше соответствовала реальным потребностям.
Общие операции в объектно-ориентированном программировании
На практике объектно-ориентированное программирование делится на две части. Одна часть включает стратегии и приемы для разработки программ (или объектно-ориентированного дизайна). Это большая тема, и поэтому мы не будет обсуждать ее в этой главе. Вторая часть ООП — это собственно структуры программирования, доступные в данном языке программирования для создания программы с использованием объектно-ориентированного подхода. В этой главе описываются следующие общие операции в ООП:
•
определение классов;
•
создание свойств, методов, а также методов доступа get и set;
100
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
•
управление доступом к классам, свойствам, методам и методам доступа;
•
создание статических свойств и методов; •
создание структур с перечислением;
•
определение и использование интерфейсов;
•
работа с наследованием, включая переопределение элементов класса.
Важные понятия и термины
Ниже приводится список важных терминов, с которыми вы столкнетесь в этой главе.
•
Атрибут — это характеристика, назначенная элементу класса (например, свойству или методу) в определении класса. Атрибуты часто используются для определения того, будет ли свойство (или метод) доступно для кода в других частях программы. Например, private
(закрытый) и public
(открытый) — это атрибуты. Закрытый метод может вызываться только кодом внутри класса, а открытый метод может вызываться любым кодом в программе.
•
Класс — это определение структуры и поведения объектов определенного типа (как шаблон или схема объектов для этого типа данных).
•
Иерархия классов — это структура многочисленных связанных классов, определяющая, какие классы наследуют функции от других классов.
•
Конструктор — это особый метод, определяемый в классе, который вызывается при создании экземпляра класса. Конструкторы обычно используются для определения значений по умолчанию или для выполнения других операций по настройке объекта.
•
Тип данных — это тип информации, который может хранить та или иная переменная. Как правило, термин тип данных имеет то же значение, что и класс.
•
Оператор «точка» — это знак точки (
.
), который в ActionScript (и многих других языках программирования) служит для указания того, что имя относится к дочернему элементу объекта (например, к свойству или методу). Например, в выражении myObject.myProperty
оператор «точка» указывает на то, что термин myProperty
ссылается на какое-то значение, являющееся элементом объекта с именем myObject
.
•
Перечисление — это набор связанных констант, сгруппированных вместе для удобства в качестве свойств одного класса.
•
Наследование — это механизм ООП, позволяющий определению одного класса включать все функции определения другого класса (и, как правило, расширять эти функции).
•
Экземпляр — фактический объект, созданный в программе.
•
Пространство имен — это, главным образом, пользовательский атрибут, обеспечивающий более полный контроль над тем, какой код может получить доступ к другому коду.
Работа с примерами из главы
Прорабатывая главу, вы можете самостоятельно тестировать приведенные в ней примеры кодов. Так как коды, приведенные в этой главе, в основном, предназначены для определения данных и манипуляциями с ними, тестирование примеров включает создание экземпляра определяемого класса, выполнение манипуляций с использованием его свойств и методов, а затем просмотр значений свойств этого экземпляра. Для просмотра этих значений необходимо занести их в экземпляр текстового поля в рабочей области или напечатать значения на панели «Вывод» с помощью функции trace()
. Эти приемы подробно описаны в разделе «Тестирование примеров кода» на странице 38.
101
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Классы
Класс — это абстрактное представление объекта. В классе хранится информация о типах данных, которые может содержать объект, и о его возможных видах поведения. Полезность такой абстракции может быть не такой заметной при создании небольших сценариев, содержащих всего несколько взаимодействующих между собой объектов. Однако по мере расширения области действия программы и увеличения числа управляемых объектов, становится очевидно, что классы обеспечивают более полный контроль над созданием и взаимодействием объектов.
Когда был создан язык ActionScript 1.0, использующие его программисты могли использовать объекты Function для создания конструктов, напоминающих классы. В версии ActionScript 2.0 была добавлена формальная поддержка для классов и введены ключевые слова, такие как class
и extends
. В ActionScript 3.0 не только сохраняется поддержка ключевых слов, введенных в ActionScript 2.0, но и добавляются новые возможности, такие как расширенное управление доступом с помощью атрибутов protected
и internal
, а также более полный контроль наследования с помощью ключевых слов final
и override
.
Если вам уже приходилось создавать классы в таких языках программирования, как Java, C++ или C#, принципы работы с ActionScript покажутся вам знакомыми. ActionScript использует те же ключевые слова и названия атрибутов, такие как class
, extends
и public
, которые обсуждаются в следующих разделах.
Примечание. В этой главе термин «свойство» обозначает любой член объекта или класса, включая переменные, константы и методы. Кроме того, несмотря на то, что термины «класс» и «статический член» нередко взаимозаменяются, в этой главе они обозначают разные понятия. Например, в этой главе словосочетание «свойства класса» относится ко всем членам класса, а не только к его статическим членам.
Определения классов
В ActionScript 3.0 определения классов используют синтаксис, подобный тому, который использовался для определения классов в ActionScript 2.0. Правильный синтаксис для определения класса вызывает ключевое слово class
, за которым следует имя класса. Тело класса, заключенное в фигурные скобки (
{}
), идет после имени класса. Например, следующий код создает класс с именем Shape, содержащий одну переменную visible
. public class Shape { var visible:Boolean = true; }
Одно значительное изменение в синтаксисе затрагивает определения классов, находящиеся внутри пакета. В ActionScript 2.0, если класс находится в пакете, имя пакета должно быть включено в объявление класса. В языке ActionScript 3.0, в котором вводится инструкция package
, имя пакета должно быть включено в объявление пакета, а не в объявление класса. Например, следующие объявления классов показывают, как класс BitmapData, включенный в пакет flash.display, определяется в ActionScript 2.0 и ActionScript 3.0.
// ActionScript 2.0 class flash.display.BitmapData {} // ActionScript 3.0 package flash.display { public class BitmapData {} }
102
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Атрибуты классов
ActionScript 3.0 позволяет изменять определения классов с помощью одного из четырех атрибутов.
Каждый из этих атрибутов, кроме internal
, необходимо явно добавлять для получения желаемого поведения. Например, если не включить атрибут dynamic
в определение класса, то для его экземпляров нельзя будет добавлять свойства во время выполнения. Чтобы присвоить атрибут, необходимо поместить его в начало определения класса, как показано в следующем коде.
dynamic class Shape {}
Обратите внимание, что в список поддерживаемых атрибутов не входит abstract
. Это объясняется тем, что в ActionScript 3.0 не поддерживаются абстрактные классы. Также обратите внимание на то, что в список не включены атрибуты private
и protected
. Эти атрибуты имеют значение только внутри определения класса и не могут применяться к самим классам. Если класс не должен открыто отображаться за пределами пакета, поместите его внутрь пакета и пометьте его атрибутом internal
. Также можно совсем опустить атрибуты internal
и public
, и компилятор автоматически добавит атрибут internal
. Если класс не должен отображаться за пределами исходного файла, в котором он определен, поместите его в конец исходного файла, под закрывающей скобкой определения пакета.
Тело класса
Тело класса, заключенное в фигурные скобки, служит для определения переменных, констант и методов класса. В следующем примере показано объявление класса Accessibility в API-интерфейсе Adobe Flash Player.
public final class Accessibility { public static function get active():Boolean; public static function updateProperties():void; }
Также внутри тела класса можно определить пространство имен. В следующем примере показано, как можно определить в теле класса пространство имен и использовать его в качестве атрибута метода этого класса.
public class SampleClass { public namespace sampleNamespace; sampleNamespace function doSomething():void; }
ActionScript 3.0 позволяет включать в тело класса не только определения, но и инструкции. Инструкции, включенные в тело класса, но находящиеся за пределами определения метода, выполняются только один раз, при первом использовании определения класса и создании связанного с ним объекта класса. В следующем примере демонстрируется вызов внешней функции, hello()
, и инструкция trace
, которая выводит на экран подтверждение при определении класса.
Атрибут Определение
dynamic
Позволяет добавлять свойства для экземпляров во время выполнения.
final
Не должен расширяться другим классом.
internal
(по умолчанию) Видимый для ссылок внутри текущего пакета.
public
Видимый для всех ссылок.
103
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
function hello():String { trace("hola"); } class SampleClass { hello(); trace("class created"); } // output when class is created hola class created
В отличие от предыдущих версий ActionScript, в ActionScript 3.0 можно определить одноименные статическое свойство и свойство экземпляра в одном теле класса. Например, следующий код объявляет статическую переменную с именем message
и переменную экземпляра с тем же именем. class StaticTest { static var message:String = "static variable"; var message:String = "instance variable"; } // In your script var myST:StaticTest = new StaticTest(); trace(StaticTest.message); // output: static variable trace(myST.message); // output: instance variable
Атрибуты свойств классов
Когда речь идет об объектной модели ActionScript, термин свойство обозначает все, что может быть членом класса, включая переменные, константы и методы. В то время как в справочнике по языку ActionScript 3.0 и компонентам этот термин имеет более узкое значение и включает только те члены класса, которые являются переменными или определяются методом get или set. В ActionScript 3.0 имеется набор атрибутов, которые могут использоваться с любым свойством класса. Эти атрибуты перечислены в следующей таблице.
Атрибуты пространства имен для управления доступом
ActionScript 3.0 обеспечивает четыре специальных атрибута для управления доступом к свойствам, определенным внутри класса: public
, private
, protected
и internal
. Атрибут public
делает свойство видимым во всем сценарии. Например, чтобы сделать метод доступным для кода за пределами пакета, необходимо объявить его с атрибутом public
. Это относится ко всем свойствам независимо от того, с использованием каких ключевых слов они объявлены: var
, const
или function
.
Атрибут Определение
internal
(по умолчанию) Видимый для ссылок внутри того же пакета.
private
Видимый для ссылок в том же классе.
protected
Видимый для ссылок в том же классе и в производных классах. public
Видимый для всех ссылок.
static
Показывает, что свойство принадлежит классу, а не экземплярам класса.
UserDefinedNamespace
Имя пространства имен, определенное пользователем.
104
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Атрибут private
делает свойство видимым только для вызывающих методов внутри определяющего класса данного свойства. Это поведение отличает его от атрибута private
в ActionScript 2.0, который разрешал подклассу доступ в закрытому свойству суперкласса. Другое значительное изменение поведение имеет отношение к доступу во время выполнения. В ActionScript 2.0 ключевое слово private
запрещало доступ только во время компиляции, а во время выполнения этот запрет можно было легко обойти. В ActionScript 3.0 это уже не удастся. Свойства, помеченные атрибутом private
, остаются недоступными как во время компиляции, так и во время выполнения. Например, следующий код создает простой класс с именем PrivateExample с одной закрытой переменной, и затем в этой переменной пытается обратиться внешний метод. В ActionScript 2.0 доступ во время компиляции был запрещен, но этот запрет можно было легко обойти с помощью оператора доступа к свойству (
[]
), который выполняет поиск свойства во время выполнения, а не во время компиляции.
class PrivateExample { private var privVar:String = "private variable"; } var myExample:PrivateExample = new PrivateExample(); trace(myExample.privVar);// compile-time error in strict mode trace(myExample["privVar"]); // ActionScript 2.0 allows access, but in ActionScript 3.0, this is a run-time error. В ActionScript 3.0 попытка обращения к свойству с помощью оператора «точка» (
myExample.privVar
) приведет к ошибке компиляции, если используется строгий режим. В противном случае ошибка появляется во время выполнения, как и в случае использования оператора доступа к свойству (
myExample["privVar"]
). В следующей таблице подведены результаты попыток обращения к закрытому свойству, которое принадлежит статическому (не динамическому) классу. В классах, объявленных с использованием атрибута dynamic
, попытки обращения к закрытым свойствам не приведут к ошибкам выполнения. Вместо этого переменная будет просто невидимой, поэтому Flash Player или Adobe® AIR™ возвращает значение undefined
. Однако ошибка компиляции возникает, если в строгом режиме используется оператор «точка». Следующий пример похож на предыдущий и отличается от него только тем, что класс PrivateExample объявляется с атрибутом dynamic. dynamic class PrivateExample { private var privVar:String = "private variable"; } var myExample:PrivateExample = new PrivateExample(); trace(myExample.privVar);// compile-time error in strict mode trace(myExample["privVar"]); // output: undefined
Динамические классы обычно возвращают значение undefined
вместо ошибки, когда внешний код пытается обратиться к закрытому свойству класса. В следующей таблице показано, что ошибка выдается, только когда оператор «точка» используется для обращения к закрытому свойству в строгом режиме.
Строгий режим Стандартный режим
оператор «точка» (
.
) ошибка компиляции ошибка выполнения
оператор «квадратные скобки» (
[]
) ошибка выполнения ошибка выполнения
105
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Атрибут protected
, впервые введенный в версии ActionScript 3.0, делает свойство видимым для вызывающих методов собственного класса или подкласса. Другими словами, защищенное свойство доступно для собственного класса и подклассов, находящихся под ним в иерархии наследования. Оно доступно даже для подклассов, находящихся в других пакетах. Для тех, кто знаком с языком ActionScript 2.0, эта функция похожа на атрибут private
в ActionScript 2.0. Атрибут protected
в ActionScript 3.0 также похож на атрибут protected
в Java, однако в версии Java также разрешает доступ для вызывающих методов в том же пакете. Атрибут protected
полезен, когда имеется свойство (переменная или метод), необходимое для подкласса, которое требуется скрыть для кода, находящегося за пределами цепи наследования.
Атрибут internal
, впервые введенный в версии ActionScript 3.0, делает свойство видимым для вызывающих методов внутри своего пакета. Это атрибут по умолчанию для кода внутри пакета, он применяется ко всем свойствам, у которых нет ни одного из перечисленных ниже атрибутов:
•
public
; •
private
; •
protected
; •
пространство имен, определенное пользователем.
Атрибут internal
похож на управление доступом по умолчанию в Java. Однако в Java нет выраженного имени для этого уровня доступа, и его можно реализовать только путем опущения других модификаторов доступа. Атрибут internal
введен в ActionScript 3.0, чтобы можно было выразить намерение сделать свойство доступным только для вызывающих методов в его собственном пакете. Атрибут static
Атрибут static
, который может использоваться со свойствами, объявленными с использованием ключевых слов var
, const
или function
, позволяет присоединить свойство к классу, а не к его экземплярам. Внешний код должен вызывать статические свойства с использованием имени класса, а не экземпляра.
Статические свойства не наследуются подклассами, но входят в цепочку области действия подкласса. Это означает, что в теле подкласса статическое свойство (переменная или метод) может использоваться без ссылки на класс, в котором оно было определено. Дополнительные сведения см. в разделе «Статические свойства не наследуются» на странице 124.
Определенные пользователем атрибуты пространства имен
В качестве альтернативы предварительно определенным атрибутам управления доступом можно создать пользовательское пространство имен и использовать его как атрибут. Для одного определения можно использовать только один атрибут пространства имен. Кроме того, нельзя использовать атрибут пространства имен в сочетании с другими атрибутами управления доступом (
public
, private
, protected
, internal
). Дополнительные сведения об использовании пространств имен см. в разделе «Пространства имен» на странице 47.
Строгий режим Стандартный режим
оператор «точка» (
.
) ошибка компиляции
undefined
оператор «квадратные скобки» (
[]
)
undefined undefined
106
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Переменные
Переменные могут объявляться с использованием ключевых слов var
и const
. Для переменных, объявленных с ключевым словом var
, значения могут меняться несколько раз во время выполнения сценария. Переменные, объявленные с ключевым словом const
называются константами. Значение присваивается им только один раз. При попытке присвоить новое значение инициализированной константе выдается ошибка. Дополнительные сведения см. в разделе «Константы» на странице 75.
Статические переменные
Статические переменные объявляются с использованием комбинации ключевого слова static
с инструкцией var
или const
. Статические переменные, присоединяемые к классу, а не к его экземпляру, полезны для хранения и совместного использования информации, которая применяется ко всему классу объектов. Например, статическую переменную уместно использовать, если требуется вести учет количества созданных экземпляров объекта или сохранить максимально допустимое количество экземпляров класса. В следующем примере создается переменная totalCount
для отслеживания количества экземпляров класса и константа
MAX_NUM
для хранения максимального числа экземпляров. Переменные totalCount
и MAX_NUM
являются статическими, так как содержат значения, применяемые ко всему классу, а не к отдельному экземпляру.
class StaticVars { public static var totalCount:int = 0; public static const MAX_NUM:uint = 16; }
Код, внешний для класса StaticVars и его подклассов, может ссылаться на свойства totalCount
и MAX_NUM
только через сам класс. Например, выполняется следующий код:
trace(StaticVars.totalCount); // output: 0 trace(StaticVars.MAX_NUM); // output: 16
К статическим переменным нельзя обратиться через экземпляр класса, поэтому следующий код возвращает ошибки.
var myStaticVars:StaticVars = new StaticVars(); trace(myStaticVars.totalCount); // error trace(myStaticVars.MAX_NUM); // error
Переменные, объявленные с использованием ключевых слов static
и const
должны инициализироваться одновременно с объявлением константы, что и делает класс StaticVars для MAX_NUM
. Для константы MAX_NUM
нельзя присвоить значение внутри конструктора или метода экземпляра. Следующий код выдаст ошибку, так как его недопустимо использовать для инициализации статической константы.
// !! Error to initialize static constant this way class StaticVars2 { public static const UNIQUESORT:uint; function initializeStatic():void { UNIQUESORT = 16; } }
107
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Переменные экземпляра
Переменные экземпляра объявляются с использованием ключевых слов var
и const
, но без ключевого слова static
. Переменные экземпляра, присоединяемые к отдельным экземплярам, а не ко всему классу, полезны для хранения значений, присущих экземпляру. Например, класс Array имеет свойство экземпляра с именем length
, которое хранит количество элементов массива, содержащееся в определенном экземпляре класса Array.
Переменные экземпляра, объявленные с ключевыми словами var
и const
, нельзя переопределять в подклассе. Однако можно для получения функции, подобной переопределению переменных, можно переопределить методы доступа get и set. Дополнительные сведения см. в разделе «Методы доступа get и set» на странице 111.
Методы
Методы — это функции, которые входят в состав определения класса. Когда создается экземпляра класса, с ним связывается метод. В отличие от функции, объявленной за пределами класса, метод нельзя использовать отдельно от экземпляра, с которым он связан.
Методы определяются с использованием ключевого слова function
. Как и свойства класса, любой их атрибут можно применить к методам, включая личные, защищенные, общедоступные, внутренние, статические или пользовательские пространства имен. Инструкция function можно использовать следующим образом:
public function sampleFunction():String {}
Также можно использовать переменную, которой присваивается выражение функции, как показано ниже.
public var sampleFunction:Function = function () {}
В большинстве случаев предпочтительнее использовать инструкцию функции, а не выражение, потому что:
•
инструкции функции более точные и простые для чтения;
•
Инструкции функции позволяют использовать ключевые слова override
и final
. Дополнительные сведения см. в разделе «Переопределение методов» на странице 122.
•
Инструкции функции создают более крепкую связь между идентификатором (именем функции) и кодом в теле метода. Так как значение переменной может быть изменено с помощью инструкции присваивания, связь между переменной и ее выражением функции может в любой момент быть разорвана. Хотя это проблему можно обойти, объявив переменную с ключевым словом const
вместо var
, такой прием лучше не использовать, так как он делает код трудным для чтения и не позволяет использовать ключевые слова override
и final
.
Единственным случаем, когда необходимо использовать именно выражение функции, является присоединение функции к объекту прототипа. Дополнительные сведения см. в разделе «Объект прототипа» на странице 131.
Методы-конструкторы
Методы-конструкторы, иногда их называют простоконструкторами, представляют собой функции с тем же именем, которым назван определяющий их класс. Любой код, включенный в метод-конструктор, выполняется при каждом создании экземпляра класса с использованием ключевого слова new
. Например, следующий код определяет простой класс Example, содержащий одно свойство с именем status
. Начальное значение переменной status
задается в функции конструктора.
108
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
class Example { public var status:String; public function Example() { status = "initialized"; } } var myExample:Example = new Example(); trace(myExample.status); // output: initialized
Методы-конструкторы могут быть только открытыми, но использование атрибута public
является необязательным. Для конструктора нельзя использовать никаких других спецификаторов управления доступом, включая private
, protected
или internal
. Кроме того, с методом-конструктором нельзя использовать пользовательское пространство имен.
Конструктор может явно вызвать конструктор находящегося непосредственно над ним суперкласса с помощью инструкции super()
. Если конструктор суперкласса не вызывается явно, компилятор автоматически вставляет вызов перед первой инструкцией в теле конструктора. Также вызывать методы суперкласса можно, используя префикс super
в качестве ссылки на суперкласс. Если в теле одного конструктора требуется использовать и конструктор super()
и префикс super
, первым должен идти конструктор super()
. В противном случае ссылка super
может повести себя не так, как предполагалось. Конструктор super()
также необходимо вызывать перед инструкциями throw
или return
. В следующем примере показано, что происходит при попытке использования ссылки super
перед вызовом конструктора super()
. Новый класс, ExampleEx, расширяет класс Example. Конструктор ExampleEx пытается получить переменную status, определенную в его суперклассе, но делает это перед вызовом super()
. Инструкция trace()
в конструкторе ExampleEx возвращает значение null
, так как переменная status
недоступна, пока не будет вызван конструктор super()
.
class ExampleEx extends Example { public function ExampleEx() { trace(super.status); super(); } } var mySample:ExampleEx = new ExampleEx(); // output: null
Хотя в конструкторе можно использовать инструкцию return
, он не может вернуть значение. Другими словами, инструкции return
не должны иметь связанных выражений или значений. Соответствующим образом, методы-конструкторы не могут возвращать значения, вследствие чего невозможно указать тип возврата.
Если для класса не определить метод-конструктор, компилятор автоматически создает пустой конструктор. Если данный класс расширяет другой, компилятор включит вызов super()
в созданный им конструктор.
109
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Статические методы
Статические методы, также называемые методами класса, — это методы, который объявляются с использованием ключевого слова static
. Статические методы, присоединяемые к классу, а не к его экземпляру, полезны для инкапсуляции, которая затрагивает не только состояние отдельного экземпляра. Так как статические методы присоединяются ко всему классу, их можно вызвать только через класс, а через его экземпляр — нет. Статические методы полезны для инкапсуляции, действие которой не ограничивается состоянием экземпляров класса. Другими словами, метод должен быть статическим, если он обеспечивает функцию, которая не оказывает прямого влияния на значение экземпляра класса. Например, класс Date имеет статический метод parse()
, который преобразует строку в число. Это статические метод, так как он не оказывает влияния на отдельные экземпляры класса. Вместо этого, метод parse()
берет строку, которая представляет собой значение даты, анализирует ее и возвращает число в формате, совместимом с внутренним представлением объекта Date. Этот метод не является методом экземпляра, так как его бессмысленно применять к одному экземпляру класса Date. Сравните статический метод parse()
с одним из методов экземпляра класса Date, таким как getMonth()
. Метод getMonth()
является методом экземпляра, так как он воздействует непосредственно на значение экземпляра, получая определенный компонент (месяц) экземпляра Date.
Так как статические методы не связаны с отдельными экземплярами, в их теле нельзя использовать ключевые слова this
и super
. Ссылки this
и super
имеют значение, только в контексте метода экземпляра.
В отличие от других языков программирования на базе классов, в ActionScript 3.0 статические методы не наследуются. Дополнительные сведения см. в разделе «Статические свойства не наследуются» на странице 124.
Методы экземпляра
Методами экземпляра являются методы, объявленные без ключевого слова static
. Методы экземпляра, присоединяемые к экземплярам, а не ко всему классу, полезны для реализации функций, затрагивающих отдельные экземпляры класса. Например, класс Array содержит метод экземпляра sort()
, который воздействует непосредственно на экземпляры Array.
В теле метода экземпляра могут содержаться и статические переменные и переменные экземпляра. Это означает, что на переменные, определенные в одном классе, можно ссылаться с использованием простого идентификатора Например, следующий класс, CustomArray, расширяет класс Array. Класс CustomArray определяет статическую переменную arrayCountTotal
для отслеживания общего числа экземпляров класса, переменную экземпляра arrayNumber
, отслеживающую порядок создания экземпляров, и метод экземпляра getPosition()
, возвращающий значения этих переменных. 110
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
public class CustomArray extends Array { public static var arrayCountTotal:int = 0; public var arrayNumber:int; public function CustomArray() { arrayNumber = ++arrayCountTotal; } public function getArrayPosition():String { return ("Array " + arrayNumber + " of " + arrayCountTotal); } }
Хотя внешний код должен ссылаться на статическую переменную arrayCountTotal
через объект класса с помощью CustomArray.arrayCountTotal
, код, находящийся внутри тела метода getPosition()
, может ссылаться непосредственно на статическую переменную arrayCountTotal
. Это относится даже к статическим переменным суперклассов. Хотя статические свойства не наследуются в ActionScript 3.0, статические свойства суперклассов входят в область действия. Например, класс Array имеет несколько статических переменных, одна из которых является константой с именем DESCENDING
. Код, находящийся в подклассе Array, может ссылаться на статическую константу DESCENDING
с помощью простого идентификатора:
public class CustomArray extends Array { public function testStatic():void { trace(DESCENDING); // output: 2 } }
Значением ссылки this
в теле метода экземпляра является ссылка на экземпляр, к которому присоединен метод. Следующий код демонстрирует, как ссылка this
указывает на экземпляр, содержащий метод.
class ThisTest { function thisValue():ThisTest { return this; } } var myTest:ThisTest = new ThisTest(); trace(myTest.thisValue() == myTest); // output: true
Наследованием методов экземпляров можно управлять с помощью ключевых слов override
и final
. Атрибут override
можно использовать для переопределения унаследованного метода, а атрибут final
— для запрета переопределения метода подклассами. Дополнительные сведения см. в разделе «Переопределение методов» на странице 122.
111
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Методы доступа get и set
Методы доступа get и set, также называемые getter и setter, позволяют соблюдать принципы сокрытия информации и инкапсуляции, обеспечивая простой в использовании интерфейс программирования для создаваемых классов. Функции get и set позволяют делать свойства класса закрытыми, но при этом пользователи класса могут обращаться к этим свойствам так, будто они обращаются к переменной класса, а не вызывают метод класса. Преимущество такого подхода заключается в том, что он позволяет отказаться от традиционных функций методов доступа с громоздкими именами, такими как getPropertyName()
и setPropertyName()
. Другое преимущество методов get и set состоит в том, что они позволяют избежать создания двух открытых функций для каждого свойства, разрешающего доступ для чтения и записи.
Следующий пример класса GetSet включает методы доступа get и set с именем publicAccess()
, которые обеспечивают доступ к закрытой переменной privateProperty
.
class GetSet { private var privateProperty:String; public function get publicAccess():String { return privateProperty; } public function set publicAccess(setValue:String):void { privateProperty = setValue; } }
Если обратиться к свойству privateProperty
напрямую, будет выдана ошибка, как показано ниже.
var myGetSet:GetSet = new GetSet(); trace(myGetSet.privateProperty); // error occurs
Вместо этого пользователь класса GetSet будет использовать то, что похоже на свойство publicAccess
, но на самом деле является парой функций методов доступа get и set, которые воздействуют на закрытое свойство privateProperty
. В следующем примере создается экземпляр класса GetSet, а затем задается значение свойства privateProperty
с помощью открытого метода доступа publicAccess
.
var myGetSet:GetSet = new GetSet(); trace(myGetSet.publicAccess); // output: null myGetSet.publicAccess = "hello"; trace(myGetSet.publicAccess); // output: hello
Функции get и set также позволяют переопределять свойства, унаследованные от суперкласса, что невозможно выполнить при использовании обычных переменных-членов класса. Переменные-члены класса, объявленные с использованием ключевого слова var
, не могут переопределяться в подклассе. Однако это ограничение не распространяется на свойства, созданные с помощью функций get и set. Для функций get и set, унаследованных от суперкласса, можно использовать атрибут override
.
112
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Связанные методы
Связанный метод, иногда называемый замыканием метода, — это метод, извлеченный из своего экземпляра. К числу связанных методов относятся методы, переданные функции в качестве аргументов или возвращенные функцией в качестве значений. Впервые в ActionScript 3.0 связанные метод уподобляется замыканию функции в том, что он сохраняет всю свою лексическую среду даже при извлечении из экземпляра. Однако между связанным методом и замыканием функции есть важное отличие: ключевое слово this
для связанного метода продолжает ссылаться на экземпляр, в котором реализуется метод, то есть остается связанным с ним. Другими словами, ссылка this
в связанном методе всегда указывает на исходный объект, в котором определен метод. Для замыканий функций ссылка this
является общей, то есть она указывает на любой объект, с которым связана функция в момент вызова.
Важно понимать суть связанных методов, если используется ключевое слово this
. Как вы помните, ключевое слово this
обеспечивает ссылку на родительский объект метода. Большинство программистов, использующих ActionScript, считают, что ключевое слово this
всегда ссылается на объект или класс, содержащий определение метода. Однако это не всегда так, если не применяется связывание метода. Например, в предыдущих версиях ActionScript ключевое слово this
не всегда ссылается на экземпляр, в котором реализован метод. Когда методы извлекаются из экземпляра в ActionScript 2.0, ссылка this
не связывается с исходным экземпляром, а переменные и методы экземпляра становятся недоступными. В ActionScript 3.0 этого не происходит, так как при передаче методов в качестве параметра автоматически создаются связанные методы. Связанные методы обеспечивают, чтобы ключевое слово this
всегда ссылалось на объект или класс, в котором определяется метод.
Следующий код определяет класс ThisTest, который содержит метод foo()
, определяющий связанный метод, и метод bar()
, возвращающий связанный метод. Внешний код создает экземпляр класса ThisTest, создает метод bar()
и сохраняет возвращенное значение в переменной myFunc
. class ThisTest { private var num:Number = 3; function foo():void // bound method defined { trace("foo's this: " + this); trace("num: " + num); } function bar():Function { return foo; // bound method returned } } var myTest:ThisTest = new ThisTest(); var myFunc:Function = myTest.bar(); trace(this); // output: [object global] myFunc(); /* output: foo's this: [object ThisTest] output: num: 3 */
Две последние строки кода показывают, что ссылка this
в связанном методе foo()
по-прежнему указывает на экземпляр класса ThisTest, несмотря на то, что ссылка this
в предшествующей строке указывает на глобальный объект. Более того, связанный метод, сохраненный в переменной myFunc
, сохранил доступ к переменным-членам класса ThisTest. Если выполнить этот же код в ActionScript 2.0, ссылки this
будут одинаковыми, а переменная num
получит значение undefined
.
113
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Добавление связанных методов имеет самое большое значение, когда речь идет об обработчиках событий, так как метод addEventListener()
требует, чтобы в качестве аргумента передавалась функция или метод. Дополнительные сведения см. в пункте «Функция прослушивателя, определенная в качестве метода класса» раздела «Прослушиватели событий» на странице 275.
Перечисления с классами
Перечисления — это пользовательские типы данных, которые создаются доля инкапсуляции небольшого набора значений. Язык ActionScript 3.0 не поддерживает специфическую функцию перечисления, в отличие от языка C++, в котором есть ключевое слово
enum
, или Java, где предусмотрен интерфейс Enumeration. Однако перечисления можно создавать с помощью классов и статических констант. Например, класс PrintJob в ActionScript 3.0 использует перечисление PrintJobOrientation для хранения набора значений, включая "landscape"
(альбомная) и "portrait"
(портретная), как показано в следующем коде. public final class PrintJobOrientation { public static const LANDSCAPE:String = "landscape"; public static const PORTRAIT:String = "portrait"; }
Класс перечисления условно объявляется с использованием атрибута final
, так как нет необходимости расширять класс. Класс включает только статические члены, а это означает, что экземпляры класса не создаются. Вместо этого, объект класса обеспечивает прямой доступ к значениям перечисления, как показано в следующем фрагменте кода.
var pj:PrintJob = new PrintJob(); if(pj.start()) { if (pj.orientation == PrintJobOrientation.PORTRAIT) { ... } ... }
Все классы перечисления в ActionScript 3.0 содержат только переменные типа String, int или uint. Преимущество использования перечислений вместо буквенной строки или числовых значений заключается в том, что в перечислениях проще выявить опечатки. Если имя перечисления введено с ошибкой, компилятор ActionScript выдает ошибку. При использовании строк компилятор не сообщает о неправильном написании слова или числа. В предыдущем примере компилятор выдает ошибку, если введено неправильное имя для константы перечисления, как показано в следующем фрагменте.
if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error
Однако компилятор не выдает ошибку, если неправильно введено строковое значение, как показано ниже.
if (pj.orientation == "portrai") // no compiler error
Второй метод создания перечислений также подразумевает создание отдельного класса со статическими свойствами для перечисления. Однако этот метод отличается тем, что каждое из статических свойств, содержит экземпляр класса вместо строки или целого числа. Например, следующий код создает класс перечисления для дней недели.
114
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
public final class Day { public static const MONDAY:Day = new Day(); public static const TUESDAY:Day = new Day(); public static const WEDNESDAY:Day = new Day(); public static const THURSDAY:Day = new Day(); public static const FRIDAY:Day = new Day(); public static const SATURDAY:Day = new Day(); public static const SUNDAY:Day = new Day(); }
Этот метод не используется в ActionScript 3.0, но используется многими разработчиками, которые предпочитают его улучшенную проверку написания. Например, метод, возвращающий значение перечисления, может ограничить возвращаемое значение определенным типом данных перечисления. Следующий код демонстрирует функцию, возвращающую день недели, а также вызов функции, использующий тип перечисления в качестве аннотации типа.
function getDay():Day { var date:Date = new Date(); var retDay:Day; switch (date.day) { case 0: retDay = Day.MONDAY; break; case 1: retDay = Day.TUESDAY; break; case 2: retDay = Day.WEDNESDAY; break; case 3: retDay = Day.THURSDAY; break; case 4: retDay = Day.FRIDAY; break; case 5: retDay = Day.SATURDAY; break; case 6: retDay = Day.SUNDAY; break; } return retDay; } var dayOfWeek:Day = getDay();
Кроме того, класс Day можно расширить, чтобы он связывал целое число с каждым днем недели и определял метод toString()
, возвращающий строковое представление дня. Попробуйте расширить класс Day таким образом в качестве упражнения.
115
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Классы встроенных ресурсов
В языке ActionScript 3.0 используются особые классы для представления встроенных ресурсов, называемые классами встроенных ресурсов. Встроенный ресурс — это ресурс, такой как звук, изображение или шрифт, включенный в SWF-файл во время компиляции. Встраивание ресурса вместо его динамической загрузки гарантирует его доступность во время выполнения, однако это увеличивает размер SWF-файла. Использование классов встроенных ресурсов в Flash
Чтобы встроить ресурс, сначала поместите его в библиотеку FLA-файла. Затем используйте свойство связывания ресурса, чтобы передать имя для его класса встроенных ресурсов. Если класса с таким именем нет в пути к классам, он создается автоматически. После этого можно создать экземпляр класса встроенных ресурсов и использовать любые определенные или унаследованные им свойства и методы. Например, следующий код можно использовать для воспроизведения встроенного звука, связанного с классом встроенных ресурсов PianoMusic.
var piano:PianoMusic = new PianoMusic(); var sndChannel:SoundChannel = piano.play();
Интерфейсы
Интерфейс — это набор объявлений методов, который позволяет несвязанным объектам взаимодействовать друг с другом. Например, ActionScript 3.0 определяет интерфейс IEventDispatcher, который содержит объявления методов, которые класс может использовать для обработки событий. Интерфейс IEventDispatcher устанавливает стандартную процедуру передачи событий между объектами. Следующий код демонстрирует определение интерфейса IEventDispatcher.
public interface IEventDispatcher { function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean = false):void; function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void; function dispatchEvent(event:Event):Boolean; function hasEventListener(type:String):Boolean; function willTrigger(type:String):Boolean; }
Интерфейсы основаны на различии между интерфейсом метода и его реализацией. Интерфейс метода включает всю информацию, необходимую для вызова этого метода, включая имя метода, всего параметры и тип возвращаемого значения. Реализация метода включает не только сведения об интерфейсе, но и исполняемые инструкции, определяющие поведение метода. Определение интерфейса содержит только интерфейсы метода, и класс, внедряющий интерфейс, несет ответственность за определение реализаций метода.
В ActionScript 3.0 класс EventDispatcher реализует интерфейс IEventDispatcher, определяя все методы интерфейса IEventDispatcher и добавляя соответствующие тела методов. Следующий код представляет собой фрагмент определения класса EventDispatcher.
116
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
public class EventDispatcher implements IEventDispatcher { function dispatchEvent(event:Event):Boolean { /* implementation statements */ } ... }
Интерфейс IEventDispatcher служит в качестве протокола, который используют экземпляры EventDispatcher для обработки событий и их отправки другим объектам, также внедрившим этот интерфейс. Интерфейс также можно описать как элемент, определяющий тип данных так же, как и класс. Соответствующим образом, интерфейс можно использовать в качестве аннотации типа, как и класс. В качестве типа данных, интерфейс можно также использовать вместе с операторами, требующими тип данных, такими как is
и as
. Однако, в отличие от класса, интерфейс не поддерживает создание экземпляров. Из-за этого отличия многие программисты называют интерфейсы абстрактными типами данных, а классы — конкретными типами данных.
Определение интерфейса
Структура определения интерфейса похожа на структуру определения класса за тем исключением, что интерфейс может содержать только методы без тел. Интерфейсы не могут содержать переменных или констант, но могут включать функции get и set. Для определения интерфейса используется ключевое слово interface
. Например, следующий интерфейс, IExternalizable, входит в пакет flash.utils в ActionScript 3.0. Интерфейс IExternalizable определяет протокол для сериализации объекта, то есть для преобразования объекта в формат, пригодный для хранения на устройстве или для транспортировки по сети. public interface IExternalizable { function writeExternal(output:IDataOutput):void; function readExternal(input:IDataInput):void; }
Обратите внимание на то, что интерфейс IExternalizable объявляется с использованием модификатора управления доступом public
. Определения интерфейса могут модифицироваться только с использованием атрибутов public
и internal
. Объявления методов внутри определения интерфейса не могут иметь модификаторов управления доступом.
В ActionScript 3.0 используется правило именования интерфейсов с заглавной буквы I
, однако в качестве имени интерфейса можно использовать любой допустимый идентификатор. Определения интерфейсов часто помещаются в верхнем уровне пакета. Определения интерфейсов нельзя помещать внутри определения класса или определения другого интерфейса.
Интерфейс может расширять один или несколько других интерфейсов. Например, следующий интерфейс IExample расширяет интерфейс IExternalizable.
public interface IExample extends IExternalizable { function extra():void; }
Любой класс, внедряющий интерфейс IExample, должен включать реализации не только для метода extra()
, но также методы writeExternal()
и readExternal()
, унаследованные от интерфейса IExternalizable.
117
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Реализация интерфейса в классе
Класс является единственным элементом языка ActionScript 3.0, который может реализовать интерфейс. Используйте ключевое слово implements
в объявлении класса, чтобы реализовать один или несколько интерфейсов. В следующем примере определяется два интерфейса (IAlpha и IBeta)
,
а также реализующий их класс Alpha.
interface IAlpha { function foo(str:String):String; } interface IBeta { function bar():void; } class Alpha implements IAlpha, IBeta { public function foo(param:String):String {} public function bar():void {} }
В классе, внедряющем интерфейс, реализованные методы должны выполнять следующие действия:
•
использовать идентификатор управления доступом public
; •
использовать то же имя, что и метод интерфейса;
•
иметь столько же параметров, сколько и методы интерфейса, а их типы данных должны соответствовать типам данных параметров методов интерфейса;
•
использовать тот же тип возвращаемых значений.
public function foo(param:String):String {}
Однако вам предоставляется некоторая свобода в наименовании параметров для реализуемых методов. Хотя реализуемый метод должен иметь столько же параметров и с теми же типами данных, что и метод интерфейса, имена параметров могут быть разными. Например, в предыдущем примере параметру метода Alpha.foo()
было присвоено имя param
.
А в методе интерфейса IAlpha.foo()
он называется str
.
function foo(str:String):String;
Также предоставляется некоторая гибкость в отношении значений параметров по умолчанию. Определение интерфейса можно включать объявления функций со значениями параметров по умолчанию. Для метода, реализующего такое объявление функции, параметра должен иметь значение по умолчанию, являющееся членом того же типа данных, что и значение, заданное в определении интерфейса, но само значение может быть другим. Например, следующий код определяет интерфейс, содержащий метод со значением параметра по умолчанию 3.
interface IGamma { function doSomething(param:int = 3):void; }
Следующее определение класса реализует интерфейс Igamma, но использует другое значение параметра по умолчанию.
118
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
class Gamma implements IGamma { public function doSomething(param:int = 4):void {} }
Такая гибкость обусловлена тем, что правила реализации интерфейса разработаны таким образом, чтобы обеспечить совместимость типа данных, а для достижения этой цели использование идентичных имен и значения по умолчанию для параметров не является обязательным.
Наследование
Наследование — это форма повторного использования кода, позволяющая программистам разрабатывать новые классы на основе существующих. Существующие классы часто называются базовыми классами или суперклассами, а новые классы — подклассами. Основным преимуществом наследования является то, что оно позволяет повторно использовать код из базового класса, не изменяя первоисточник. Более того, при наследовании не требуется изменять метод взаимодействия других классов с базовым. В отличие от изменения существующего класса, который уже тщательно протестирован и, возможно, используется, наследование позволяет работать с классом как с интегрированным модулем, который можно расширить с помощью дополнительных свойств или методов. Таким образом, для обозначения класса, наследующего свойства и методы другого класса используется ключевое слово extends
(расширяет).
Наследование также позволяет использовать в коде преимущества полиморфизма. Полиморфизм — это возможность использовать одно имя для метода, который ведет себя по-разному при применении к разным типам данных. Самый простой пример — это базовый класс Shape, который имеет два подкласса с именами Circle и Square. Класс Shape определяет метод area()
, который возвращает площадь фигуры. При применении полиморфизма метод area()
можно вызывать для объектов типа Circle и Square, получая при этом правильные расчеты. Наследование делает возможным полиморфизм, так как позволяет подклассам наследовать и переопределять (override) методы из базового класса. В следующем примере метод area()
переопределяется классами Circle и Square.
119
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
class Shape { public function area():Number { return NaN; } } class Circle extends Shape { private var radius:Number = 1; override public function area():Number { return (Math.PI * (radius * radius)); } } class Square extends Shape { private var side:Number = 1; override public function area():Number { return (side * side); } } var cir:Circle = new Circle(); trace(cir.area()); // output: 3.141592653589793 var sq:Square = new Square(); trace(sq.area()); // output: 1
Так как каждый класс определяет тип данных, наследование создает определенные отношения между базовым и расширяющим классами. Подкласс гарантированно получает все свойства базового класса, то есть экземпляр подкласса можно в любой момент заменить экземпляр базового класса. Например, если метод определяет параметр типа Shape, разрешается передать аргумент типа Circle, так как класс Circle расширяет класс Shape, как показано в следующем примере.
function draw(shapeToDraw:Shape) {} var myCircle:Circle = new Circle(); draw(myCircle);
Свойства экземпляра и наследование
Свойство экземпляра, определенное с использованием ключевых слов function
, var
или const
, наследуется всеми подклассами, если оно не объявлено с атрибутом private
в базовом классе. Например, класс Event в ActionScript 3.0 имеет ряд подклассов, наследующих свойства, общие для всех объектов событий. Для некоторый типов событий класс Event содержит все свойства, необходимые для определения события. Эти типы событий не требуют других свойств экземпляра, кроме определенных в классе Event. К таким событиям относятся событие complete
, которое происходит после успешной загрузки данных, и событие connect
, которое происходит после успешной установки соединения. В следующем примере приводится фрагмент из кода класса Event, в котором представлены некоторые свойства и методы, наследуемые подклассами. Так как свойства наследуются, к ним может обращаться экземпляр любого подкласса.
120
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
public class Event { public function get type():String; public function get bubbles():Boolean; ... public function stopPropagation():void {} public function stopImmediatePropagation():void {} public function preventDefault():void {} public function isDefaultPrevented():Boolean {} ... }
Для других типов событий требуются уникальные свойства, недоступные в классе Event. Эти события определяются с использованием подклассов класса Event, чтобы к числу свойств, определенных в классе Event, можно было добавить новые свойства. В качестве примера можно привести подкласс MouseEvent, который добавляет свойства, уникальные для событий, связанных с движением или щелчками мыши, таких как mouseMove
и click
. В следующем примере приводится фрагмент кода класса MouseEvent, в котором определяются свойства, существующие только в подклассе, а в базовом классе — нет.
public class MouseEvent extends Event { public static const CLICK:String= "click"; public static const MOUSE_MOVE:String = "mouseMove"; ... public function get stageX():Number {} public function get stageY():Number {} ... }
Идентификаторы управления доступом и наследование
Если свойство объявлено с использованием ключевого слова public
, оно будет доступно для всего кода. Это означает, что ключевое слово public
, в отличие от слов private
, protected
и internal
, не накладывает ограничений на наследование свойств.
Если свойство объявлено с использованием ключевого слова private
, оно доступно только в определяющем его классе, то есть не наследуется никакими подклассами. Такое поведение отличается от предыдущих версий ActionScript, где поведение ключевого слова private
больше напоминало поведение protected
в ActionScript 3.0.
Ключевое слово protected
указывает, что свойство доступно не только для определяющего его класса, но и для всех подклассов. В отличие от ключевого слова protected
в языке программирования Java, в ActionScript 3.0 protected
не делает свойство доступным для всех других классов в одном пакете. В ActionScript 3.0 свойство, объявленное с использованием ключевого слова protected
доступно только для подклассов. Более того, защищенное свойство доступно для подкласса независимо от того, находится он в том же пакете, что и базовый класс, или в другом.
Чтобы ограничить доступность свойства только тем пакетом, в котором оно определено, следует использовать только ключевое слово internal
без других идентификаторов управления доступом. Идентификатор управления доступом internal
используется по умолчанию, когда нет других атрибутов. Свойство, объявленное с идентификатором internal
, наследуется только подклассами, включенными в тот же пакет.
121
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
В следующем примере демонстрируется влияние каждого из идентификаторов управления доступом на наследование в пределах пакета. Следующий код определяет основной класс приложения AccessControl и два других класса с именами Base и Extender. Класс Base находится в пакете foo, а его подкласс Extender находится в пакете bar. Класс AccessControl импортирует только класс Extender и создает экземпляр Extender, который пытается обратиться к переменной str
, определенной в классе Base. Переменная str
объявляется с идентификатором public
, поэтому код компилируется и выполняется, как показано в следующем фрагменте.
// Base.as in a folder named foo package foo { public class Base { public var str:String = "hello"; // change public on this line } } // Extender.as in a folder named bar package bar { import foo.Base; public class Extender extends Base { public function getString():String { return str; } } } // main application class in file named AccessControl.as package { import flash.display.MovieClip; import bar.Extender; public class AccessControl extends MovieClip { public function AccessControl() { var myExt:Extender = new Extender(); trace(myExt.str);// error if str is not public trace(myExt.getString()); // error if str is private or internal } } }
Чтобы оценить влияние других идентификаторов управления доступом на компиляцию и выполнения предыдущего примера, измените атрибут переменной str
на private
, protected
или internal
, удалив или скрыв с помощью комментария следующую строку из класса AccessControl
:
trace(myExt.str);// error if str is not public
122
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Запрет переопределения переменных
Свойства, объявленные с ключевыми словами var
и const
наследуются, но не могут быть переопределены. Переопределение свойства выполняется в подклассе. Единственный тип свойств, допускающий переопределение, — это методы, то есть свойства, объявленные с ключевым словом function
. Хотя нельзя переопределить переменную экземпляра, можно получить подобный результат путем создания методов get и set для переменной экземпляра и переопределения этих методов. Дополнительные сведения см. в разделе «Переопределение методов» на странице 122.
Переопределение методов
Переопределение метода означает переопределение поведения наследуемого метода. Статические методы не наследуются и не могут переопределяться. Однако методы экземпляра наследуются подклассами и могут переопределяться, если выполняется два следующих условия:
•
Метод экземпляра объявлен в базовом классе без использования ключевого слова final
. Атрибут final
рядом с методом экземпляра указывает на то, что программист явно запретил переопределение метода подклассами.
•
Метод экземпляра объявлен в базовом классе без использования идентификатора управления доступом private
. Если метод помечен в базовом классе идентификатором private
, то при определении одноименного метода в подклассе не требуется использовать ключевое слово override
, так как метод базового класса не будет доступен для подкласса.
Чтобы переопределить метод экземпляра, соответствующий этим критериям, в определении метода подкласса должно использоваться ключевое слово override
и соблюдаться соответствие версии суперкласса по следующим аспектам:
•
Переопределенный метод должен иметь тот же уровень управления доступом, что и метод базового класса. Методы с атрибутом internal должны иметь тот же уровень управления доступом, что и методы без идентификатора. •
Переопределенный метод должен иметь столько же параметров, что и метод базового класса.
•
Параметры переопределенного метода должны иметь те же аннотации типа данных, что и параметры в метода базового класса.
•
Переопределенный метод должен иметь от же тип возвращаемого значения, что и метод базового класса.
Однако параметры в переопределенном методе и параметры в базовом классе могут иметь разные имена, при условии что число параметров и тот же тип данных совпадают.
Инструкция super
Переопределяя метод, программисты нередко хотят расширить поведение метода суперкласса, а не заменить его полностью. Для этого требуется механизм, позволяющий методу подкласса вызывать версию этого же метода в суперклассе. Инструкция super
обеспечивает такой механизм тем, что содержит ссылку на непосредственный суперкласс. В следующем примере определяется класс Base, содержащий метод thanks()
, и его подкласс Extender, переопределяющий метод thanks()
. Метод Extender.thanks()
использует инструкцию super
для вызова Base.thanks()
.
123
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
package { import flash.display.MovieClip; public class SuperExample extends MovieClip { public function SuperExample() { var myExt:Extender = new Extender() trace(myExt.thanks()); // output: Mahalo nui loa } } } class Base { public function thanks():String { return "Mahalo"; } } class Extender extends Base { override public function thanks():String { return super.thanks() + " nui loa"; } }
Переопределение методов get и set
Несмотря на то, что нельзя переопределять переменные суперкласса, можно переопределять методы get и set. Например, следующий код переопределяет метод get currentLabel
, определенный в классе MovieClip в ActionScript 3.0.
package { import flash.display.MovieClip; public class OverrideExample extends MovieClip { public function OverrideExample() { trace(currentLabel) } override public function get currentLabel():String { var str:String = "Override: "; str += super.currentLabel; return str; } } }
Инструкция trace()
в конструкторе класса OverrideExample выдает значение Override: null
, которое указывает на то, что код смог переопределить унаследованное свойство currentLabel
.
124
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Статические свойства не наследуются
Статические свойства не наследуются подклассами Это означает, что к статическим свойствам невозможно обратиться через экземпляр подкласса. Статическое свойство можно получить только через объект определяющего его класса. Например, следующий код определяет базовый класс Base и его подкласс Extender. Статическая переменная test
определена в классе Base. Код, представленный в следующем фрагменте, не компилируется в строгом режиме и выдает ошибку выполнения в стандартном режиме.
package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); trace(myExt.test);// error } } } class Base { public static var test:String = "static"; } class Extender extends Base { }
Обратиться к статической переменной test
можно только через объект класса, как показано в следующем коде.
Base.test;
Однако можно определить свойство экземпляра с тем же именем, что и статическое свойство. Такое свойство экземпляра может быть определено в том же классе, что и статическое, или в подклассе. Например, в классе Base в предыдущем примере можно было бы определить свойство экземпляра test
. Следующий код компилируется и выполняется без ошибок, так как класс Extender наследует свойство экземпляра. Этот код также будет компилироваться и выполняться, если определение переменной экземпляра test будет перемещено, а не скопировано, в класс Extender.
125
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); trace(myExt.test);// output: instance } } } class Base { public static var test:String = "static"; public var test:String = "instance"; } class Extender extends Base {}
Статические свойства и цепочка области действия
Несмотря на то, что статические свойства не наследуются, они находятся в цепочке области действия определяющего их класса, а также его подклассов. Поэтому статические свойства, так сказать, находятся в области действия и класса, в котором они определены, и его подклассов. Это означает, что статическое свойство напрямую доступно в теле определяющего его класса и всех его подклассов. В следующем примере модифицируются классы, определенные в предыдущем примере, чтобы продемонстрировать то, что статическая переменная test
, определенная в классе Base, находится в области действия класса Extender. Другими словами, класс Extender может обращаться к статической переменной test
, не добавляя к ней в качестве префикса имя класса, определяющего test
.
126
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); } } } class Base { public static var test:String = "static"; } class Extender extends Base { public function Extender() { trace(test); // output: static } }
Если в одном классе или суперклассе определено свойство экземпляра с тем же именем, что и статическое свойство, то свойство экземпляра имеет более высокий приоритет в цепочке области действия. Свойство экземпляра, так сказать, затеняет статическое свойство, то есть значение свойства экземпляра используется вместо значения статического свойства. Например, следующий код демонстрирует, что если класс Extender определяет переменную экземпляра с именем test
, инструкция trace()
использует ее значение вместо значения статической переменной.
127
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
package { import flash.display.MovieClip; public class StaticExample extends MovieClip { public function StaticExample() { var myExt:Extender = new Extender(); } } } class Base { public static var test:String = "static"; } class Extender extends Base { public var test:String = "instance"; public function Extender() { trace(test); // output: instance } }
Дополнительные темы
Этот раздел начинается с изложения краткой истории языка ActionScript и объектно-ориентированного программирования, а затем переходит к обсуждению объектной модели ActionScript 3.0 и того, как она позволяет ускорить работу новой версии виртуальной машины ActionScript Virtual Machine (AVM2) по сравнению с предыдущими версиями Flash Player со старой версией ActionScript Virtual Machine (AVM1).
История объектно-ориентированного программирования на языке ActionScript Так как язык ActionScript 3.0 создан на основе предыдущих версий ActionScript, будет полезно проследить развитие объектной модели ActionScript. Язык ActionScript сначала представлял собой простой механизм создания сценариев для ранних версий инструмента разработки Flash. Впоследствии, программисты стали создавать с помощью ActionScript все более сложные приложения. В ответ на потребности таких программистов в каждом новом выпуске расширялись возможности языка, упрощающие создание сложных приложений.
ActionScript 1.0
ActionScript 1.0 — это версия языка, используемого в Flash Player 6 и более ранних версиях. С самого начала объектная модель языка ActionScript строилась на базе концепции, согласно которой объект является основополагающим типом данных. Объект ActionScript представляет собой составной тип данных с группой свойств. Применительно к объектной модели термин свойства включает все, что присоединяется к объекту, то есть переменные, функции или методы. 128
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Хотя первое поколение языка ActionScript не поддерживает определение классов с помощью ключевого слова class
, класс можно определить с помощью объекта особого типа, так называемого прототипа. Вместо того чтобы определять с помощью ключевого слова class
абстрактного класса, из которого затем можно создать конкретные экземпляры, как в языках на базе классов, таких как Java и C++, языки на базе прототипов, такие как ActionScript 1.0, используют в качестве модели (или прототипа) для новых объектов существующий объект. В языках на базе классов объект может указывать на класс, используемый в качестве его шаблона, а в языках на базе прототипа объект указывает на другой объект, свой прототип, который является его шаблоном. Чтобы создать класс в ActionScript 1.0, необходимо определить функцию-конструктор для этого класса. В ActionScript функции — это не абстрактные определения, а конкретные объекты. Созданная функция-
конструктор служит в качестве прототипичного объекта для экземпляров этого класса. Следующий код создает класс Shape и определяет одно свойство visible
, которому задается значение по умолчанию true
.
// base class function Shape() {} // Create a property named visible. Shape.prototype.visible = true;
Эта функция-конструктор определяет класс Shape и создает его экземпляр с помощью оператора new
, как показано ниже.
myShape = new Shape();
Объект функции-конструктора Shape()
может служить прототипом для экземпляров не только класса Shape, но и его подклассов, то есть классов, расширяющих класс Shape.
Создание подкласса для класса Shape происходит в два этапа. На первом этапе создается класс посредством определения его функции-конструктора, как показано ниже.
// child class function Circle(id, radius) { this.id = id; this.radius = radius; }
На втором этапе с помощью оператора new
класс Shape объявляется в качестве прототипа класса Circle. По умолчанию любой создаваемый класс использует в качестве прототипа класс Object, то есть Circle.prototype
пока содержит родовой объект (экземпляр класса Object). Чтобы указать, что прототипом класса Circle является класс Shape, а не Object, используйте следующий код, который изменяет значение Circle.prototype
так, что оно вместо родового объекта будет содержать объект Shape.
// Make Circle a subclass of Shape. Circle.prototype = new Shape();
Теперь классы Shape и Circle связаны друг с другом отношением наследования, часто называемым цепочкой прототипов. На следующей схеме представлены отношения в цепочке прототипов.
Object.prototype
Shape.prototype
Circle.prototype
129
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Базовым классом, который находится в конце любой цепочки прототипов, является класс Object. Класс Object содержит статическое свойство Object.prototype
, которое указывает на базовый прототипичный объект для всех объектов, созданных в ActionScript 1.0. Следующим объектом в нашем примере цепочки прототипов является объект Shape. Свойство Shape.prototype
не задавалось явно, поэтому оно по-прежнему содержит родовой объект (экземпляр класса Object). Последняя ссылка в этой цепочке — класс Circle, связанный со своим прототипом, классом Shape (свойство Circle.prototype
содержит объект Shape).
Если создать экземпляр класса Circle class, как в следующем примере, он унаследует цепочку прототипов класса Circle. // Create an instance of the Circle class. myCircle = new Circle();
Как вы помните, мы создали свойство visible
, которое является членом класса Shape. В нашем примере свойство visible
не существует в объекте myCircle
, являясь членом только для объекта Shape. Несмотря на это следующая строка кода возвращает значение true
.
trace(myCircle.visible); // output: true
Flash Player может установить, что объект myCircle
наследует свойство
visible
, поднявшись по цепочке прототипов. Выполняя код, проигрыватель Flash Player сначала выполняет поиск свойства visible
среди свойств объекта myCircle
, но не находит его. После этого Flash Player выполняет поиск в объекте Circle.prototype
, но в нем также не оказывается свойства visible
. Поднимаясь выше по цепочке прототипов, проигрыватель наконец находит свойство visible
, определенное в объекте Shape.prototype
, и выводит его значение.
Для простоты, в этом разделе опущены многие детали и сложности цепочки прототипов, вместо этого мы стремимся предоставить достаточный объем информации, необходимый для общего понимания объектной модели ActionScript 3.0.
ActionScript 2.0
В язык ActionScript 2.0 были введены новые ключевые слова, такие как class
, extends
, public
и private
, которые позволяют определять классы так, как это привыкли делать все, кто работает с языками Java и C++. Важно понимать, что в основе языков ActionScript 1.0 и ActionScript 2.0 лежит один и тот же механизм наследования. В версии ActionScript 2.0 просто добавлены новые элементы синтаксиса для определения классов. Цепочка прототипов работает одинаково в обеих версиях языка.
Новый синтаксис, введенный в ActionScript 2.0, позволяет определять классы более простым для многих программистов способом, как показано ниже.
// base class class Shape { var visible:Boolean = true; }
Обратите внимание, что в языке ActionScript 2.0 были введены аннотации типов для использования при проверке типов во время компиляции. Это позволяет объявить, что свойство visible
в предыдущем примере должно содержать только логическое значение. Новое ключевое слово extends
также упрощает процесс создания подклассов. В следующем примере, двухэтапный процесс в ActionScript 1.0 выполняется одним действие с помощью ключевого слова extends
.
130
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
// child class class Circle extends Shape { var id:Number; var radius:Number; function Circle(id, radius) { this.id = id; this.radius = radius; } }
Теперь конструктор объявляется в составе определения класса, и свойства класса id
и radius
также должны быть явно объявлены.
В языке ActionScript 2.0 также добавлена поддержка для определения интерфейсов, позволяющая еще больше усовершенствовать объектно-ориентированные программы с помощью формально определенных протоколов для взаимодействия объектов.
Объект класса в ActionScript 3.0
Общая парадигма объектно-ориентированного программирования, которая чаще всего ассоциируется с языками Java и C++, использует классы для определения типов объектов. Языки программирования, применяющие эту парадигму, как правило, используют классы также для создания экземпляров типа данных, определяемого классом. Язык ActionScript использует классы в обеих целях, но, будучи разработанным на базе прототипов, он также имеет еще одну интересную отличительную черту. ActionScript создает для каждого определения класса особый объект класса, который обеспечивает совместное использование поведения и состояния. Однако для многих программистов, работающих с языком ActionScript, это отличие не применяется на практике. Язык ActionScript 3.0 разработан таким образом, что создавать сложные объектно-
ориентированные приложения ActionScript можно, не используя этих специальных объектов классов и даже не имея о них никакого понятия. В этом разделе объекты классов подробно описаны для опытных программистов, которые желают использовать их в своей работе.
На следующей схеме показана структура объекта класса, представляющего простой класс A, определенный с помощью инструкции class A {}
.
T
CA
P
A
C
A
T
A
Class.prototype Object.prototype
делегат
конструктор
делегат
прототип
тип
признаки
131
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Каждый прямоугольник в схеме представляет объект. Каждый объект в схеме имеет подстрочный символ «А», который указывает на то, что он принадлежит классу А. Объект класса (СА) содержит ссылки на ряд других важных объектов. Объект признаков экземпляра (ТА) хранит свойства экземпляра, объявленные в определении класса. Объект признаков класса (ТСА) представляет внутренний тип класса и хранит статические свойства, определенные классом (подстрочный символ «С» обозначает «класс»). Объект прототипа (PA) всегда ссылается на объект класса, к которому он изначально присоединен с помощью свойства constructor
.
Объект признаков
Объект признаков, впервые введенный в версии ActionScript 3.0, служит для повышения производительности. В предыдущих версиях ActionScript, поиск имени мог занимать много времени, так как проигрывателю Flash Player требовалось пройти всю цепочку прототипов. В ActionScript 3.0 поиск имени выполняется намного эффективней и быстрей, так как наследуемые свойства копируются из суперклассов в объект признаков подклассов.
Программный код не может обратиться к объекту признаков напрямую, но его присутствие повышает производительность и оптимизирует использование памяти. Объект признаков предоставляет для AVM2 подробные сведения о макете и содержимом класса. Располагая такими данными, AVM2 может значительно сократить время выполнения, так как виртуальная машина во многих случаях создает прямые инструкции для обращения к свойствам или непосредственно вызывает методы, не затрачивая времени на поиск имен.
Благодаря объекту признаков, объем памяти, занимаемый объектом, может быть намного меньше, чем у подобных объектов в предыдущих версиях ActionScript. Например, если класс не объявлен как динамический (то есть является фиксированным), его экземпляру не требуется хэш-таблица для динамически добавляемых свойств, и он может содержать лишь указатель на объекты признаков и несколько слотов для фиксированных свойств, определенных в классе. В результате, объект, который требовал 100 байтов памяти в ActionScript 2.0, в версии ActionScript 3.0 будет требовать лишь 200 байтов.
Примечание. Объект признаков — это внутренняя деталь реализации. Нельзя гарантировать, что он не изменится или совсем не исчезнет в будущих версиях ActionScript.
Объект прототипа
Каждый объект класса ActionScript имеет свойство prototype
, которое представляет собой на объект прототипа этого класса. Объект прототипа является наследием ActionScript как языка на базе прототипов. Дополнительные сведения см. в разделе «История объектно-ориентированного программирования на языке ActionScript» на странице 127.
Свойство prototype
предназначено только для чтения: его нельзя изменить так, чтобы оно указывало на другие объекты. А в предыдущих версиях ActionScript свойство prototype
можно было переназначить, чтобы оно указывало на другой класс. Хотя свойство prototype
доступно только для чтения, это ограничение не распространяется на указываемый им объект прототипа. Другими словами, к объекту прототипа можно добавлять новые свойства. Свойства, добавляемые к объекту прототипа, совместно используются всеми экземплярами класса.
Цепочка прототипов, которая являлась единственным механизмом наследования в предыдущих версиях ActionScript, выполняет лишь второстепенную роли в ActionScript 3.0. Основной механизм наследования, то есть наследование фиксированных свойств, осуществляется на внутреннем уровне объектом признаков. Фиксированное свойство — это переменная или метод, объявленный как часть определения класса. Наследование фиксированных свойств также называется наследованием класса, так как этот механизм наследования связан с такими ключевыми словами, как class
, extends
и override
. 132
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Цепочка прототипов обеспечивает альтернативный механизм наследования, отличающийся от наследования фиксированный свойств большей динамичностью. Объект прототипа класса можно добавлять свойства не только в составе определения класса, но и во время выполнения через свойство prototype
объекта класса. Однако обратите внимание, что если компилятор запущен в строгом режиме, то свойства, добавленные в объект прототипа, могут быть недоступны, если класс не объявлен с использование ключевого слова dynamic
. Рассмотрим присоединение нескольких свойств к объекту прототипа на примере класса Object. Методы toString()
и valueOf()
класса Object на самом деле являются функциями, которые назначены свойствам объекта прототипа класса Object. Ниже приводится пример того, как может выглядеть объявление этих методов теоретически (фактическая реализация выглядит по-другому из-за деталей реализации).
public dynamic class Object { prototype.toString = function() { // statements }; prototype.valueOf = function() { // statements }; }
Как говорилось выше, свойство можно присоединить к объекту прототипа класса за рамками определения класса. Например, метод toString()
можно также определить за пределами определения класса Object, как показано ниже.
Object.prototype.toString = function() { // statements };
Однако, в отличие от наследования фиксированных свойств, наследование прототипа не требует ключевого слова override
, если требуется переопределить метод в подклассе. Например, если требуется переопределить метод valueOf()
в подклассе класса Object, это можно сделать одним из трех методов. Во-первых, можно определить метод valueOf()
для объекта прототипа подкласса в определении класса. Следующий код создает подкласс Foo класса Object и переопределяет метод valueOf()
объекта прототипа Foo в составе определения класса. Так как каждый класс является наследником класса Object, использовать ключевое слово extends
не требуется.
dynamic class Foo { prototype.valueOf = function() { return "Instance of Foo"; }; }
Во-вторых, можно определить метод valueOf()
для объекта прототипа класса Foo в составе определения класса, как в следующем коде.
Foo.prototype.valueOf = function() { return "Instance of Foo"; };
133
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
В-третьих, можно определить фиксированное свойство valueOf()
в составе класса Foo. Этот метод отличается от остальных тем, что в нем объединено наследование фиксированных свойств с наследованием прототипов. Если в каком-либо подклассе класса Foo потребуется переопределить метод valueOf()
, необходимо использовать ключевое слово override
. Следующий код демонстрирует определение метода valueOf()
в качестве фиксированного свойства класса Foo.
class Foo { function valueOf():String { return "Instance of Foo"; } }
Пространство имен AS3
В результате существования двух механизмов наследования, наследования фиксированных свойств и наследования прототипов, появляется интересная проблема совместимости в отношении свойств и методов базовых классов. Для совместимости со спецификацией языка ECMAScript, на которой основан ActionScript, требуется наследование прототипов, то есть методы и свойства базового класса должны определяться в объекте прототипа класса. С другой стороны, для совместимости с ActionScript 3.0 требуется наследование фиксированных свойств, то есть свойства и методы базового класса присоединяются через определение класса с помощью ключевых слов const
, var
и function
. Кроме того, использование фиксированных свойств вместо свойств прототипов может значительно повысить производительность во время выполнения.
ActionScript 3.0 решает эту проблему с помощью использования для основных классов как наследования прототипов, так и наследования фиксированных свойств. Каждый базовый класс содержит два набора свойств и методов. Один набор определяется для объекта прототипа с целью обеспечения совместимости со спецификацией ECMAScript, а другой определяется с использование фиксированных свойств и пространством имен AS3 для обеспечения совместимости с ActionScript 3.0. Пространство имен AS3 обеспечивает удобный механизм выбора одного из двух наборов свойств и методов. Если не используется пространство имен AS3, экземпляр базового класса наследует свойства и методы, определенные в объекте прототипа базового класса. Если используется пространство имен AS3, экземпляр базового класса наследует версии AS3, так как фиксированные свойства всегда имеют более высокий приоритет, чем свойства прототипа. Другими словами, если доступно фиксированное свойство, оно всегда используется вместо одноименного свойства прототипа.
Можно избирательно использовать AS3-версию свойства или метода, указав его с помощью пространства имен AS3. Например, следующий код использует AS3-версию метода Array.pop()
.
var nums:Array = new Array(1, 2, 3); nums.AS3::pop(); trace(nums); // output: 1,2
Также можно использовать директиву use namespace
, чтобы открыть пространство имен AS3 для всех определений в блоке кода. Например, следующий код использует директиву use namespace
, чтобы открыть пространство имен AS3 для методов pop()
и push()
. use namespace AS3; var nums:Array = new Array(1, 2, 3); nums.pop(); nums.push(5); trace(nums) // output: 1,2,5
134
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
ActionScript 3.0 также предоставляет параметры компилятора для каждого набора свойств, чтобы пространство AS3 можно было применить ко всей программе. Параметр компилятора -as3
обозначает пространство имен AS3, а параметр компилятора -es
обозначает наследование прототипов (
es
— это сокращение от ECMAScript). Чтобы открыть пространство имен AS3 для всей программы, задайте параметру компилятора -as3
значение true
, а параметру компилятора -es
— значение false
. Чтобы использовать версии прототипа, задайте параметрам компилятора противоположные значения. По умолчанию в Adobe Flex Builder 3 и Adobe Flash CS4 Professional используются следующие настройки компилятора: -as3 = true
и -es = false
.
Если вы планируете расширять базовые классы и переопределять методы, то необходимо разобраться в том, как пространство имен AS3 может повлиять на способ объявления переопределенного метода. Если используется пространство имен AS3, в любом переопределении метода базового класса также должно использоваться пространство имен AS3 вместе с атрибутом override
. Если пространство имен AS3 не используется, то при переопределении метода базового класса в подклассе не следует использовать пространство имен AS3 и ключевое слово override
.
Пример: GeometricShapes
Пример приложения GeometricShapes демонстрирует, как ряд понятий и возможностей объектно-
ориентированного программирования можно применить с использованием ActionScript 3.0, включая:
•
определение классов, •
расширение классов,
•
полиморфизм и ключевое слово override
,
•
определение, расширение и реализацию интерфейсов.
Кроме того, в примере используется «фабричный метод», который создает экземпляры классов, объявляя в качестве возвращаемого значения экземпляр интерфейса, и использует возвращенный объект в общем виде.
Получить файлы приложения для этого примера можно на странице www.adobe.com/go/learn_programmingAS3samples_flash_ru. Файлы приложения GeometricShapes находятся в папке Samples/GeometricShapes. Приложение состоит из следующих файлов.
Файл Описание
GeometricShapes.mxml
или
GeometricShapes.fla
Основной файл приложения Flash (FLA) или Flex (MXML).
com/example/programmingas3/geometricshapes/IGeometricShape.as Базовый интерфейс, определяющий методы, которые должны быть реализованы всеми классами приложения GeometricShapes.
com/example/programmingas3/geometricshapes/IPolygon.as Интерфейс, определяющий методы, которые должны быть реализованы всеми классами приложения GeometricShapes с несколькими сторонами.
com/example/programmingas3/geometricshapes/RegularPolygon.as Тип геометрической фигуры, равные стороны которого симметрично противоположны относительно центра фигуры.
135
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Определение классов GeometricShapes
Приложение GeometricShapes дает пользователю возможность указать тип и размер геометрической фигуры. После этого выдается описание фигуры, ее площадь и ее периметр.
В приложении использован обычный пользовательский интерфейс, включающий несколько элементов управления для выбора типа фигуры, указания ее размера и отображения описания. Самая интересная часть приложения кроется под поверхностью, в структуре самих классов и интерфейсов.
Это приложение работает с геометрическими фигурами, но не отображает их графически. Оно обеспечивает небольшую библиотеку классов и интерфейсов, которые будут повторно использованы в другом примере главы (см. «Пример: SpriteArranger» на странице 334). В примере SpriteArranger фигуры отображаются в графическом виде, и пользователь может выполнять манипуляции с ними. За основу данного примера берется структура классов, созданная в приложении GeometricShapes.
Классы и интерфейсы, определяющие геометрические фигуры в этом примере, представлены на следующей схеме с использованием нотации UML (Унифицированный язык моделирования).
Классы в примере GeometricShapes
com/example/programmingas3/geometricshapes/Circle.as Тип геометрической фигуры, определяющей круг.
com/example/programmingas3/geometricshapes/EquilateralTriangle.as Подкласс класса RegularPolygon, определяющий равносторонний треугольник.
com/example/programmingas3/geometricshapes/Square.as Подкласс класса RegularPolygon, определяющий равносторонний прямоугольник.
com/example/programmingas3/geometricshapes/GeometricShapeFactory.as Класс, содержащий фабричный метод для создания фигур заданного типа и размера.
Файл Описание
<< interface >>
IGeometricShape
+getArea (): Number
+describe (): Strin
<< interface >>
IPolygon
+getPerimeter (): Number
+getSumOfAngles (): Number
Circle
+d
iameter:Number
+Circle () : Circle
+getArea () : Number
+describe () : String
+getCircumference
() : Number
+num
Sides : int
+sideLength : Number
+RegularPolygon (): RegularPolygon
+getSumOfAngles (): Number
+getPerimeter (): Number
+getArea (): Number
+describe (): Stri
ng
RegularPolygon
+EquilateralTriangle (): EquilateralTriangle
+getArea (): Number
+describe (): String
EquilateralTriangle
+Square (): Square
+getArea (): Number
+des
cribe ()
: String
Square
136
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Определение общего поведения с помощью интерфейсов
Это приложение GeometricShapes работает с тремя типами фигур: кругами, квадратами и равносторонними треугольниками. Структура классов GeometricShapes начинается с очень простого интерфейса, IGeometricShape, в котором перечислены методы, общие для фигур всех трех типов.
package com.example.programmingas3.geometricshapes { public interface IGeometricShape { function getArea():Number; function describe():String; } }
Интерфейс определяет два метода: метод getArea()
, который вычисляет и возвращает площадь фигуры, и метод describe()
, который генерирует текстовое описание свойств фигуры.
Мы также хотим узнать периметр каждой фигуры. Однако периметр круга называется окружностью, он вычисляется по особой формуле, поэтому его поведение отличается от поведения треугольника и квадрата. Несмотря на это, между треугольниками, квадратами и другими многоугольниками существует достаточно большое сходство, чтобы для них можно было определить новый класс интерфейса: IPolygon. Интерфейс IPolygon также довольно простой, как показано ниже.
package com.example.programmingas3.geometricshapes { public interface IPolygon extends IGeometricShape { function getPerimeter():Number; function getSumOfAngles():Number; } }
Этот интерфейс определяет два метода, общие для всех многоугольников: метод getPerimeter()
, который изменяет совокупный размер всех сторон, и метод getSumOfAngles()
, который вычисляет сумму всех внутренних углов.
Интерфейс IPolygon расширяет интерфейс IGeometricShape, то есть любой класс, реализующий интерфейс IPolygon, должен объявить все четыре метода: два из IGeometricShape и два из IPolygon.
Определение классов фигур
Разобравшись с методами, общими для каждого типа фигур, можно определить сами классы фигур. С точки зрения количества реализуемых методов, самой простой фигурой является круг (класс Circle), как показано ниже.
137
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
package com.example.programmingas3.geometricshapes { public class Circle implements IGeometricShape { public var diameter:Number; public function Circle(diam:Number = 100):void { this.diameter = diam; } public function getArea():Number { // The formula is Pi * radius * radius. var radius:Number = diameter / 2; return Math.PI * radius * radius; } public function getCircumference():Number { // The formula is Pi * diameter. return Math.PI * diameter; } public function describe():String { var desc:String = "This shape is a Circle.\n"; desc += "Its diameter is " + diameter + " pixels.\n"; desc += "Its area is " + getArea() + ".\n"; desc += "Its circumference is " + getCircumference() + ".\n"; return desc; } } }
Класс Circle реализует интерфейс IGeometricShape, поэтому он должен включать код для методов getArea()
и describe()
. Помимо этого, определяется метод getCircumference()
, уникальный для класса Circle. Класс Circle также объявляет свойство diameter
, которого нет у классов многоугольников, так как оно содержит значение диаметра.
Остальные два типа фигур (квадраты и равносторонние треугольники) имеют больше общих свойств: все их стороны равны, а для расчета их периметра и суммы внутренних углов используются общие формулы. В действительности, эти формулы применяются и к другим правильным многоугольникам, которые вам также придется определять в будущем. Класс RegularPolygon будет суперклассом для классов Square и EquilateralTriangle. В суперклассе можно определить все общие методы, чтобы их не нужно было определять по отдельности в каждом подклассе. Ниже приводится код класса RegularPolygon:
138
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
package com.example.programmingas3.geometricshapes { public class RegularPolygon implements IPolygon { public var numSides:int; public var sideLength:Number; public function RegularPolygon(len:Number = 100, sides:int = 3):void { this.sideLength = len; this.numSides = sides; } public function getArea():Number { // This method should be overridden in subclasses. return 0; } public function getPerimeter():Number { return sideLength * numSides; } public function getSumOfAngles():Number { if (numSides >= 3) { return ((numSides - 2) * 180); } else { return 0; } } public function describe():String { var desc:String = "Each side is " + sideLength + " pixels long.\n"; desc += "Its area is " + getArea() + " pixels square.\n"; desc += "Its perimeter is " + getPerimeter() + " pixels long.\n"; desc += "The sum of all interior angles in this shape is " + getSumOfAngles() + " degrees.\n"; return desc; } } }
В первую очередь, класс RegularPolygon объявляет два свойства, общие для всех правильных многоугольников: длину каждой стороны (свойство sideLength
) и количество сторон (свойство numSides
).
Класс RegularPolygon реализует интерфейс IPolygon и объявляет все четыре метода интерфейса IPolygon. Два из них, getPerimeter()
и getSumOfAngles()
, реализуются с помощью общих формул.
139
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Так как для каждой фигуры используется своя формула метода getArea()
, версия базового класса метода не может содержать общую логику, которую могли бы наследовать методы подклассов. Вместо этого возвращается значение по умолчанию 0, указывающее на то, что площадь не вычислена. Чтобы правильно вычислить площадь каждой фигуры, подклассы класса RegularPolygon должны самостоятельно переопределить метод getArea()
.
Следующий код для класса EquilateralTriangle демонстрирует переопределение метода getArea()
.
package com.example.programmingas3.geometricshapes { public class EquilateralTriangle extends RegularPolygon { public function EquilateralTriangle(len:Number = 100):void { super(len, 3); } public override function getArea():Number { // The formula is ((sideLength squared) * (square root of 3)) / 4. return ( (this.sideLength * this.sideLength) * Math.sqrt(3) ) / 4; } public override function describe():String { /* starts with the name of the shape, then delegates the rest of the description work to the RegularPolygon superclass */ var desc:String = "This shape is an equilateral Triangle.\n"; desc += super.describe(); return desc; } } }
Ключевое слово override
указывает на то, что метод EquilateralTriangle.getArea()
намеренно переопределяет метод getArea()
суперкласса RegularPolygon. Когда вызывается метод EquilateralTriangle.getArea()
, он вычисляет площадь по формуле из предыдущего кода, а код RegularPolygon.getArea()
никогда не выполняется.
Класс EquilateralTriangle не определяет собственную версию метода getPerimeter()
. Когда вызывается метод EquilateralTriangle.getPerimeter()
, этот вызов передается вверх по цепочке наследования и выполняет под в методе
getPerimeter()
суперкласса RegularPolygon.
Конструктор EquilateralTriangle()
использует инструкцию super()
, чтобы сделать явный вызов конструктора RegularPolygon()
своего суперкласса. Если бы оба конструктора имели одинаковый набор параметров, можно было бы совсем опустить конструктор EquilateralTriangle()
, а вместо этого вызывался бы конструктор RegularPolygon()
. Однако конструктору RegularPolygon()
требуется дополнительный параметр, numSides
. Поэтому конструктор EquilateralTriangle()
делает вызов super(len, 3)
, который передает параметр ввода len
и значение 3, указывающее на то, что у фигуры будет три стороны.
Метод describe()
также использует инструкцию super()
, но по-другому, чтобы вызвать метод describe()
суперкласса RegularPolygon. Метод EquilateralTriangle.describe()
сначала задает в качестве значения строковой переменной desc
предложение, описывающее тип фигуры. Затем он получает результаты метода RegularPolygon.describe()
, вызвав super.describe()
, и добавляет результат в строку desc
.
140
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Здесь не приводится подробное описание класса Square, но он похож на класс EquilateralTriangle, в котором есть конструктор и собственные версии методов getArea()
и describe()
.
Полиморфизм и фабричный метод
Набор классов, в которых используются интерфейсы и наследования, может применяться для достижения разных интересных целей. Например, все классы фигур, описанные выше, либо реализуют интерфейс IGeometricShape, либо расширяют реализующий его суперкласс. Поэтому, если переменная определена в качестве экземпляра IGeometricShape, совершенно не нужно знать, является ли она на самом деле экземпляром класса Circle или Square, чтобы вызвать ее метод describe()
.
Следующий код демонстрирует, как это происходит.
var myShape:IGeometricShape = new Circle(100); trace(myShape.describe());
Когда вызывается метод myShape.describe()
, он выполняет метод Circle.describe()
, так как несмотря на то, что переменная определена как экземпляр IGeometricShape, ее базовым классом является Circle.
Этот пример демонстрирует принцип полиморфизма в действии: один и тот же метод может вызывать результаты другого выполняемого в данный момент кода в зависимости от класса того объекта, для которого вызывался метод.
Приложение GeometricShapes применяет этот тип полиморфизма на базе интерфейса, используя упрощенную версию шаблона, известного под названием «фабричный метод». Термин фабричный метод обозначает функцию, которая возвращает объект, базовый тип данных или содержимое которого может быть разным в зависимости от контекста.
Описанный здесь класс GeometricShapeFactory определяет фабричный метод с именем createShape()
.
141
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
package com.example.programmingas3.geometricshapes { public class GeometricShapeFactory { public static var currentShape:IGeometricShape; public static function createShape(shapeName:String, len:Number):IGeometricShape { switch (shapeName) { case "Triangle": return new EquilateralTriangle(len); case "Square": return new Square(len); case "Circle": return new Circle(len); } return null; } public static function describeShape(shapeType:String, shapeSize:Number):String { GeometricShapeFactory.currentShape = GeometricShapeFactory.createShape(shapeType, shapeSize); return GeometricShapeFactory.currentShape.describe(); } } }
Фабричный метод createShape()
позволяет конструкторам подклассов фигур определять детали создаваемых ими экземпляров и возвращать новые объекты в качестве экземпляров IGeometricShape, чтобы они проходили более общую обработку в приложении.
Метод describeShape()
в предыдущем примере демонстрирует, как приложение может использовать фабричный метод для получения общей ссылки на более конкретный объект. Приложение может получить описание для только что созданного объекта Circle, как показано ниже.
GeometricShapeFactory.describeShape("Circle", 100);
Затем метод describeShape()
вызывает фабричный метод createShape()
с теми же параметрами, сохраняя новый объект Circle в статической переменной currentShape
, которая была задана в качестве объекта IGeometricShape. После этого вызывается метод describe()
объекта currentShape
, и в результате разрешения этот метод автоматически выполняет метод Circle.describe()
, возвращая подробное описание круга.
Расширение примера приложения
Настоящая сила интерфейсов и наследования становится очевидной, когда требуется расширить или изменить приложение.
142
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Объектно-ориентированное программирование на языке ActionScript
Допустим, требуется добавить новую фигуру, пятиугольник, в этот пример приложения. Для этого нужно создать новый класс Pentagon, который расширяет класс RegularPolygon и определяет собственные версии методов getArea()
и describe()
. После этого следует добавить новый элемент «Pentagon» (Пятиугольник) в комбинированное поле пользовательского интерфейса приложения. Вот и все! Класс Pentagon автоматически получает методы getPerimeter()
и getSumOfAngles()
, наследуя их от класса RegularPolygon. Так как класс Pentagon является потомком класса, который реализует интерфейс IGeometricShape, его экземпляр также можно создать в качестве экземпляра IGeometricShape. Это означает, что для добавления нового типа фигуры не требуется изменять сигнатуру методов класса GeometricShapeFactory (и, следовательно, не требуется изменять коды, использующие класс GeometricShapeFactory).
В качестве упражнения, попробуйте добавить класс Pentagon в пример GeometricShapes, чтобы оценить, насколько интерфейсы и наследование упрощают добавление новых возможностей в приложение.
143
Глава 6. Работа с датами и временем
Исчисление времени — не главное в программном приложении, но порой это ключевой фактор его качества. Язык ActionScript 3.0 предлагает эффективные способы управления календарными датами, временем и временными интервалами. За эту функциональность отвечают два основных класса: класс Date и новый класс Timer в пакете flash.utils.
Основы работы с датами и временем
Введение в работу с датами и временем
Даты и время — это тип информации, часто используемый в программах ActionScript. В качестве примера возможной функциональности вам может понадобиться знать точный день недели или определить, сколько времени пользователь тратит на той или иной экран. В языке ActionScript класс Date используется для представления отдельного момента времени, включая данные о дате и времени. В экземпляре Date содержатся отдельные значения даты и времени, включая год, месяц, число, день недели, час, минуты, секунды, миллисекунды и часовой пояс. Язык ActionScript расширяет эту функциональность с помощью класса Timer, который позволяет выполнять какое-либо действие с определенной задержкой или с заданным интервалом.
Общие задачи, связанные с датой и временем
В этой главе рассказывается об общих задачах, связанных с работой с датой и временем. Они перечислены ниже.
•
Работа с объектами Date.
•
Получение текущей даты и времени.
•
Получение отдельных данных даты и времени (дни, годы, часы, минуты и т.д.).
•
Выполнение арифметических операций над датами и временем.
•
Перевод времени между часовыми поясами
•
Многократное выполнение действий.
•
Выполнение действий после заданного интервала.
Важные понятия и термины
Ниже приводится список важных терминов, с которыми вы столкнетесь в этой главе.
•
Время UTC: универсальное скоординированное время (англ. Coordinated Universal Time) — время в «нулевом поясе». Остальные временные зоны определяются относительно времени UTC с пометкой, на сколько часов время опережает или отстает от UTC.
144
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
Работа с примерами из главы
Прорабатывая главу, вы можете самостоятельно тестировать приведенные в ней примеры кодов. Так как в образцах кода в этой главе в основном фигурируют объекты Date, при тестировании примеров необходимо будет просматривать значения переменных, используемых в примерах. Для этого можно записать значения в экземпляр текстового поля в рабочей области или вывести значения на панель «Вывод» с помощью функции trace()
. Эти техники подробнее описываются в разделе «Тестирование примеров кода» на странице 38.
Управление календарными датами и временем
Все функции управления датами и временем в ActionScript 3.0 собраны в классе верхнего уровня Date. В классе Date содержатся методы и свойства, позволяющие обрабатывать даты и время в формате UTC или в формате местного часового пояса. UTC — это стандартное время, равное гринвичскому (GMT).
Создание объектов Date
Из всех ключевых классов класс Date обладает одним из наиболее гибких методов конструкторов. Его можно вызвать четырьмя способами.
Во-первых, если у конструктора Date()
нет параметров, он возвращает объект, содержащий текущие дату и время по местному часовому поясу. Вот пример:
var now:Date = new Date();
Во-вторых, если у конструктора Date()
только один числовой параметр, то им исчисляется количество миллисекунд с 1 января 1970 г., в результате чего метод возвращает соответствующий объект Date. Обратите внимание, что значение в миллисекундах — это количество миллисекунд с 1 января 1970 г. в формате UTC. Тем не менее, объект Date выводит значения по местному времени, кроме случаев, когда используются методы вывода значений в формате UTC. При создании нового объекта Date с помощью единственного параметра milliseconds не забывайте о разнице между своим часовым поясом и UTC. Следующие инструкция создают объект Date, установленный на полночь 1 января 1970 г. в формате UTC:
var millisecondsPerDay:int = 1000 * 60 * 60 * 24; // gets a Date one day after the start date of 1/1/1970 var startTime:Date = new Date(millisecondsPerDay);
В-третьих, в конструктор Date()
можно передавать несколько числовых параметров. Он распознает в этих параметрах соответственно год, месяц, число, час, минуту, секунду и миллисекунду и возвращает нужный объект Date. Эти параметры ввода считаются по местному времени, а не UTC. Следующие инструкции получают объект Date, установленный на полночь 1 января 2000 г. по местному времени:
var millenium:Date = new Date(2000, 0, 1, 0, 0, 0, 0);
В-четвертых, можно передать конструктору Date()
единую строку-параметр. Он будет пытаться разобрать эту строку на компоненты даты и времени, а затем возвратить соответствующий объект Date. При использовании этого подхода рекомендуется включать конструктор Date()
в блок try..catch
для отлавливания ошибок разбора. Конструктор Date()
принимает несколько форматов строк, перечисленных в справочнике по языку ActionScript 3.0 и компонентам. Следующая инструкция инициализирует новый объект Date с помощью строкового значения:
var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM");
Если конструктору Date()
не удается разобрать строку-параметр, он не генерирует исключение. Тем не менее, получившийся объект Date будет содержать неверное значение даты.
145
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
Получение значений даты и времени
Значение разных единиц времени можно извлечь из объекта Date с помощью свойств или методов класса Date. Каждое из следующих свойств возвращает значение единицы времени из объекта Date:
•
свойство fullYear
;
•
свойство month
, обозначаемое числами от 0 до 11, где 0 — это январь, а 11 — декабрь;
•
свойство date
, обозначаемое числом календарного дня от 1 до 31;
•
свойство day
, обозначающее день недели в числовом формате, начиная с 0 (воскресенье);
•
свойство hours
в диапазоне от 0 до 23;
•
свойство minutes
;
•
свойство seconds
;
•
свойство milliseconds
.
В действительности класс Date предлагает несколько способов получения этих значений. Например, значение месяца из объекта Date можно получить четырьмя разными методами:
•
свойство month
;
•
метод getMonth()
;
•
свойство monthUTC
;
•
метод getMonthUTC()
.
Все четыре способа одинаково эффективны, поэтому выбор будет зависеть от конкретных целей.
Перечисленные свойства представляют компоненты значения даты в целом. Например, свойство milliseconds не может быть больше 999, потому что при достижении им значения 1000 значение seconds возрастает на 1, а свойство milliseconds сбрасывается до 0. Если вам нужно получить значение объекта Date в миллисекундах с 1 января 1970 года (UTC), можно воспользоваться методом getTime()
. Схожий с ним метод setTime()
позволяет изменять значение существующего объекта Date в миллисекундах с 1 января 1970 года (UTC). Арифметические операции с датами и временем
С помощью класса Date можно складывать и вычитать даты и время. Значения дат хранятся в миллисекундах, поэтому перед сложением или вычитанием необходимо перевести остальные значения в миллисекунды.
Если в вашем приложении планируется часто выполнять арифметические действия с датами и временем, вам может быть полезно создать константы, содержащие общие значения единиц времени в миллисекундах:
public static const millisecondsPerMinute:int = 1000 * 60; public static const millisecondsPerHour:int = 1000 * 60 * 60; public static const millisecondsPerDay:int = 1000 * 60 * 60 * 24;
Выполнять арифметические операции с датами, используя стандартные единицы времени, будет гораздо проще. В приведенном ниже коде значение даты устанавливается на один час вперед от текущего времени с помощью методов getTime()
и setTime()
.
var oneHourFromNow:Date = new Date(); oneHourFromNow.setTime(oneHourFromNow.getTime() + millisecondsPerHour);
Еще один способ задать значение даты и времени — создать новый объект Date только с помощью параметра milliseconds. Например, в приведенном ниже коде для вычисления одной даты к другой прибавляется 30 дней. 146
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
// sets the invoice date to today's date var invoiceDate:Date = new Date(); // adds 30 days to get the due date var dueDate:Date = new Date(invoiceDate.getTime() + (30 * millisecondsPerDay));
Далее, константа millisecondsPerDay
умножается на 30 для получения 30 дней, а результат добавляется к значению invoiceDate
и используется для установки значения dueDate
. Перевод времени между часовыми поясами
Арифметические операции с датами и временем пригодятся, если вы хотите преобразовать даты одного часового пояса в другой. Это делается методом getTimezoneOffset()
, который возвращает значение в минутах, соответствующее разнице между часовым поясом объекта Date и UTC. Он возвращает значение в минутах, потому что не все пояса отличаются строго на час: для некоторых разница с соседними поясами составляет полчаса.
В примере ниже показано, как использовать смещение между часовыми поясами для преобразования даты из местного времени в UTC. Для преобразования сначала вычисляется значение часового пояса в миллисекундах, а потом значение Date изменяется на эту величину:
// creates a Date in local time var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM"); // converts the Date to UTC by adding or subtracting the time zone offset var offsetMilliseconds:Number = nextDay.getTimezoneOffset() * 60 * 1000; nextDay.setTime(nextDay.getTime() + offsetMilliseconds);
Управление временными интервалами
При разработке приложений в Adobe Flash CS4 Professional у вас есть доступ к временной шкале, с помощью которой можно отслеживать покадровое выполнение приложения. Однако в «чистых» проектах ActionScript придется полагаться на другие механизмы счисления времени.
Циклы и таймеры
В некоторых языках программирования необходимо задавать собственные схемы счисления времени с помощью инструкций циклов типа for
или do..while.
Инструкции циклов, как правило, работают с той скоростью, какую позволяет локальный компьютер, то есть на каких-то компьютерах приложения будут выполняться быстрее, на каких-то медленнее. Если приложению требуется постоянный временной интервал, его можно привязать к календарю или к часам. Во многих приложениях: играх, анимациях, счетчиках реального времени — требуются надежные механизмы отсчета, которые будут работать одинаково вне зависимости от компьютера.
Класс ActionScript 3.0 Timer предлагает для этого удачное решение. С помощью модели событий ActionScript 3.0 класс Timer отправляет событие таймера после достижения заданного временного интервала.
Класс Timer
Предпочтительный способ обработки функций в языке ActionScript 3.0 — использование класса Timer (flash.utils.Timer), с помощью которого можно отправлять события при достижении заданного интервала.
147
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
Для запуска таймера нужно сначала создать экземпляр класса Timer, который будет сообщать, как часто генерировать событие таймера и сколько раз это нужно делать.
Например, ниже показано, как создавать экземпляр Timer, который будет отправлять событие каждую секунду в течение 60 секунд:
var oneMinuteTimer:Timer = new Timer(1000, 60);
Объект Timer отправляет объект TimerEvent каждый раз при достижении заданного интервала. Тип события объекта TimerEvent — timer
(определяется константой TimerEvent.TIMER
). Объект TimerEvent содержит те же свойства, что и стандартный объект Event.
Если экземпляру Timer задано фиксированное число интервалов, он также отправит событие timerComplete
(определяемое константой TimerEvent.TIMER_COMPLETE
) при достижении завершающего интервала.
Вот образец небольшого приложения, в котором демонстрируется работа класса Timer:
package { import flash.display.Sprite; import flash.events.TimerEvent; import flash.utils.Timer; public class ShortTimer extends Sprite { public function ShortTimer() { // creates a new five-second Timer var minuteTimer:Timer = new Timer(1000, 5); // designates listeners for the interval and completion events minuteTimer.addEventListener(TimerEvent.TIMER, onTick); minuteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete); // starts the timer ticking minuteTimer.start(); } public function onTick(event:TimerEvent):void { // displays the tick count so far // The target of this event is the Timer instance itself. trace("tick " + event.target.currentCount); } public function onTimerComplete(event:TimerEvent):void { trace("Time's Up!"); } } }
При создании класса ShortTimer создается экземпляр Timer, который будет отсчитывать каждую секунду в течение пяти секунд. Затем к таймеру добавляются два прослушивателя, один из которых будет прослушивать секундные отметки, а второй — событие timerComplete
. Затем таймер начинает отсчет, и с этого момента метод onTick()
выполняется с интервалом в одну секунду. 148
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
Метод onTick()
просто выводит текущий счет секунд. По прошествии пяти секунд выполняется метод onTimerComplete()
, сообщающий, что время вышло.
При выполнении этого примера у вас в консоли или окне трассировки должны отображаться следующие строки, по одной в секунду:
tick 1 tick 2 tick 3 tick 4 tick 5 Time's Up!
Временные функции в пакете flash.utils
В языке ActionScript 3.0 есть несколько временных функций, схожих с функциями ActionScript 2.0. Это функции пакетного уровня в пакете flash.utils, и работают они точно так же, как и в ActionScript 2.0.
Эти функции оставлены в языке ActionScript 3.0 в целях обратной совместимости. Компания Adobe не рекомендует использовать их во вновь разрабатываемых приложениях на ActionScript 3.0. В целом, использовать в приложениях класс Timer правильнее и удобнее.
Пример: простые аналоговые часы
Пример с простыми аналоговыми часами иллюстрирует два из описанных в этой главе принципов работы с датами и временем:
•
получение текущей даты и времени и извлечение значений для часов, минут и секунд;
•
использовании класса Timer для задания ритма приложению.
Файлы приложений для этого примера можно найти по адресу: www.adobe.com/go/learn_programmingAS3samples_flash_ru. Файлы приложения SimpleClock находятся в папке Samples/SimpleClock. Приложение состоит из следующих файлов.
Функция Описание
clearInterval(id:uint):void
Отменяет заданный вызов метода setInterval()
.
clearTimeout(id:uint):void
Отменяет указанный вызов метода setTimeout()
.
getTimer():int
Возвращает количество миллисекунд, прошедших с момента инициализации проигрывателя Adobe
®
Flash
®
или среды Adobe
®
AIR
™
.
setInterval(closure:Function, delay:Number, ... arguments):uint Выполняет функцию с заданным интервалом (в миллисекундах).
setTimeout(closure:Function, delay:Number, ... arguments):uint Выполняет указанную функцию с заданной задержкой (в миллисекундах).
149
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
Определение класса SimpleClock
Пример с часами очень прост, но полезно уметь грамотно работать и с простыми приложениями, чтобы в будущем понимать, как их можно усложнить и усовершенствовать. В приложении SimpleClock используется класс SimpleClock для обработки задач запуска и отсчета времени, а также еще один класс AnalogClockFace собственно для отображения времени.
Ниже приведен код для определения и инициализации класса SimpleClock (обратите внимание, что в варианте Flash класс SimpleClock является расширением класса Sprite):
public class SimpleClock extends UIComponent { /** * The time display component. */ private var face:AnalogClockFace; /** * The Timer that acts like a heartbeat for the application. */ private var ticker:Timer;
У этого класса есть два важных свойства:
•
свойство face
, являющееся экземпляром класса AnalogClockFace;
•
свойство ticker
, являющееся экземпляром класса Timer.
Класс SimpleClock использует конструктор по умолчанию. Метод initClock()
отвечает за установку: создает циферблат и запускает экземпляр Timer.
Создание циферблата
В следующих строках кода SimpleClock создается циферблат для отображения времени:
/** * Sets up a SimpleClock instance. */ public function initClock(faceSize:Number = 200) { // creates the clock face and adds it to the display list face = new AnalogClockFace(Math.max(20, faceSize)); face.init(); addChild(face); // draws the initial clock display face.draw();
Файл Описание
SimpleClockApp.mxml
или
SimpleClockApp.fla
Основной файл приложения Flash (FLA) или Flex (MXML).
com/example/programmingas3/simpleclock/SimpleClock.as Основной файл приложения.
com/example/programmingas3/simpleclock/AnalogClockFace.as Рисует круглый циферблат с часовой, минутной и секундной стрелками.
150
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
Размер циферблата можно передать в методе initClock()
. Если значение faceSize
не передается, то размер по умолчанию составит 200 пикселов.
Затем приложение инициализирует циферблат и добавляет его к списку отображения с помощью метода addChild()
, наследуемого от класса DisplayObject. Далее вызывается метод AnalogClockFace.draw()
, который один раз отображает циферблат с текущим временем. Запуск таймера
После создания циферблата метод initClock()
настраивает таймер: // creates a Timer that fires an event once per second ticker = new Timer(1000); // designates the onTick() method to handle Timer events ticker.addEventListener(TimerEvent.TIMER, onTick); // starts the clock ticking ticker.start();
Сначала этот метод создает экземпляр Timer, который будет отправлять событие каждую секунду (каждые 1000 миллисекунд). Так как конструктору Timer()
не передается второй параметр repeatCount
, Timer будет многократно повторяться. Метод SimpleClock.onTick()
будет выполняться раз в секунду при получении события timer
:
public function onTick(event:TimerEvent):void { // updates the clock display face.draw(); }
Метод AnalogClockFace.draw()
просто рисует циферблат и стрелки. Отображение текущего времени
Подавляющая часть кода в классе AnalogClockFace отвечает за создание на циферблате отображаемых элементов. При инициализации класса AnalogClockFace рисуется круг, внутри него рядом с каждой часовой меткой пишется число, а затем создаются три объекта Shape: один для часовой стрелки, один для минутной и один для секундной.
После запуска приложения SimpleClock каждую секунду вызывается метод AnalogClockFace.draw()
, как показано ниже:
/** * Called by the parent container when the display is being drawn. */ public override function draw():void { // stores the current date and time in an instance variable currentTime = new Date(); showTime(currentTime); }
Этот метод сохраняет значение текущего времени в переменной, чтобы время не изменилось в процессе отрисовки стрелок часов. Затем вызывается метод showTime()
, который отображает стрелки часов, как показано ниже:
151
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с датами и временем
/** * Displays the given Date/Time in that good old analog clock style. */ public function showTime(time:Date):void { // gets the time values var seconds:uint = time.getSeconds(); var minutes:uint = time.getMinutes(); var hours:uint = time.getHours(); // multiplies by 6 to get degrees this.secondHand.rotation = 180 + (seconds * 6); this.minuteHand.rotation = 180 + (minutes * 6); // Multiply by 30 to get basic degrees, then // add up to 29.5 degrees (59 * 0.5) // to account for the minutes. this.hourHand.rotation = 180 + (hours * 30) + (minutes * 0.5); }
Сначала этот метод извлекает значения часов, минут и секунд текущего времени. Затем эти значения используются для расчета угла каждой из стрелок. Так как секундная стрелка делает полный оборот за 60 секунд, ее угол каждую секунду меняется на 6 градусов (360/60). Минутная стрелка каждую минуту смещается на одинаковое количество градусов.
Часовая стрелка тоже меняет свое положение каждую минуту, чтобы отражать ход времени. Каждый час она смещается на 30 градусов (360/12), а каждую минуту — на полградуса (делим 30 градусов на 60 минут). 152
Глава 7. Работа со строками Класс String содержит методы, которые позволяют работать с текстовыми строками. Строки играют важную роль при работе со многими объектами. Методы, описанные в этой главе, полезны при работе со строками, которые используются в таких объектах, как TextField, StaticText, XML, ContextMenu и FileReference.
Строки представляют собой последовательность символов. ActionScript 3.0 поддерживает символы ASCII и «Юникод». Основные сведения о строках
Введение в работу со строками
В языке программистов строка обозначает текстовое значение, то есть последовательность букв, цифр или других символов, объединенных в одно значение. Например, этот код создает переменную с типом данных String и назначает ей строковый литерал.
var albumName:String = "Three for the money";
Как показывает этот пример, в языке ActionScript текст строкового значения заключается в двойные или одинарные кавычки. Ниже приведены другие примеры строк.
"Hello" "555-7649" "http://www.adobe.com/"
Манипулируя любым фрагментом текста в ActionScript, вы работаете со строковым значением. В ActionScript класс String является типом данных, который можно использовать для работы с текстовыми значениями. Экземпляры String часто используются в качестве свойств, параметров методов и т.д. других классов ActionScript.
Общие операции со строками
Ниже перечислены общие операции со строками, обсуждаемые в этой главе:
•
создание объектов String;
•
работа со специальными символами, такими как символ новой строки, табуляция, непечатные символы;
•
измерение длины строки;
•
изоляция отдельных символов строки;
•
объединение строк;
•
сравнение строк;
•
поиск, извлечение и замена частей строки;
•
преобразование букв строки в заглавные или строчные.
153
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Важные понятия и термины
Ниже приводится список важных терминов, с которыми вы столкнетесь в этой главе.
•
ASCII — это система для представления текстовых знаков и символов в компьютерных программах. Система ASCII поддерживает 26-буквенный английский алфавит и ограниченный набор дополнительных символов.
•
Символ — это наименьшая единица текстовых данных (одна буква или один символ).
•
Сцепление — это объединение нескольких строковых значений путем добавления одной строки в конец другой, в результате чего образуется новое строковое значение.
•
Пустая строка — это строка, которая не содержит текста, пробелов или других символов и выглядит как ""
. Следует отличать пустую строку от переменной String с нулевым значением. Переменная String с нулевым значением — это переменная, которой не назначен экземпляр String, в то время как пустой строке присвоен экземпляр String со значением, не содержащим символов.
•
Строка — это текстовое значение (последовательность символов).
•
Строковый литерал — это строковое значение, которое явно записано в коде как текстовое значение, заключенное в двойные или одинарные кавычки.
•
Подстрока — это строка, которая входит в состав другой строки.
•
Юникод — это стандартная система для представления текстовых знаков и символов в компьютерных программах. Система «Юникод» позволяет использовать любой символ любой письменности.
Работа с примерами из главы
Прорабатывая главу, вы можете самостоятельно тестировать приведенные в ней примеры кодов. Так как коды, приведенные в этой главе, в основном, предназначены для манипуляций с текстом, тестирование примеров включает просмотр значений переменных, использованных в примерах, путем их записи в экземпляр текстового поля в рабочей области или путем отображения значений на панель вывода с помощью функции trace()
. Эти приемы подробно описаны в разделе «Тестирование примеров кода» на странице 38.
Создание строк
Класс String служит для представления строковых (текстовых) данных в языке ActionScript 3.0. Строки ActionScript поддерживают символы ASCII и «Юникод». Сроку проще всего определить с помощью строкового литерала. Чтобы объявить строковый литерал, используйте прямые двойные кавычки (
"
) или одиночные кавычки (
'
). Например, следующие две строки эквивалентны друг другу:
var str1:String = "hello"; var str2:String = 'hello';
Также объявить строку можно с помощью оператора new
, как показано ниже.
var str1:String = new String("hello"); var str2:String = new String(str1); var str3:String = new String(); // str3 == ""
Следующие две строки эквивалентны друг другу:
var str1:String = "hello"; var str2:String = new String("hello");
154
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Чтобы использовать одинарные кавычки (
'
) в строковом литерале, в котором в качестве разделителей выбраны одинарные кавычки (
'
), маскируйте их символом обратной косой черты (
\
). Подобным образом, чтобы использовать двойные кавычки (
"
) в строковом литерале, в котором в качестве разделителей выбраны одинарные кавычки (
"
), маскируйте их символом обратной косой черты (
\
). Следующие две строки эквивалентны друг другу: var str1:String = "That's \"A-OK\""; var str2:String = 'That\'s "A-OK"';
Выбирать одинарные либо двойные кавычки следует исходя из того, какие кавычки существуют в строковом литерале, как показано ниже.
var str1:String = "ActionScript <span class='heavy'>3.0</span>"; var str2:String = '<item id="155">banana</item>';
Помните, что в языке ActionScript проводится различие между прямой одинарной кавычкой (
'
) и левой или правой одинарной кавычкой (
'
или '
). То же относится и к двойным кавычкам. Для выделения строковых литералов используются прямые кавычки. Вставляя текст из другого источника в код ActionScript, следите за тем, чтобы использовались правильные символы.
Как показано в следующей таблице, символ обратной косой черты (
\
) можно использовать для определения других символов в строковых литералах. Свойство length
Каждая строка имеет свойство length
, которое представляет количество символов в строке.
var str:String = "Adobe"; trace(str.length); // output: 5
Пустая строка и нулевая строка имеют нулевую длину, как показано в следующем примере.
ESC-
последовательность
Символ
\b
Возврат
\f
Новая страница
\n
Новая строка
\r
Возврат каретки
\t
Табуляция
\unnnn
Символ кодировки «Юникод» с кодом, выраженным шестнадцатеричным числом nnnn, например \u263a
.
\\xnn
Символ ASCII с кодом, выраженным шестнадцатеричным числом nn
\'
Одиночная кавычка
\"
Двойная кавычка
\\
Одна обратная косая черта
155
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
var str1:String = new String(); trace(str1.length); // output: 0 str2:String = ''; trace(str2.length); // output: 0
Работа с символами в строках
Каждый символ в строке имеет позицию индекса в строке (целое число). Позиция индекса первого символа — 0. Например, в следующей строке символ y
занимает позицию 0, а символ w
— позицию 5.
"yellow"
Анализировать отдельные символы в различных позициях строки можно с помощью метода charAt()
и charCodeAt()
, как показано ниже.
var str:String = "hello world!"; for (var i:int = 0; i < str.length; i++) { trace(str.charAt(i), "-", str.charCodeAt(i)); }
При выполнении этого кода возвращается следующий вывод.
h - 104 e - 101 l - 108 l - 108 o - 111 - 32 w - 119 o - 111 r - 114 l - 108 d - 100 ! - 33 Также можно использовать коды символов, чтобы определить строку с помощью метода fromCharCode()
, как в следующем коде.
var myStr:String = String.fromCharCode(104,101,108,108,111,32,119,111,114,108,100,33); // Sets myStr to "hello world!"
Сравнение строк
Для сравнения строк можно использовать следующие операторы: <
, <=
, !=
, ==
, =>
и >
. Эти операторы можно использовать с условными выражениями if
и while
, как показано в следующем примере. var str1:String = "Apple"; var str2:String = "apple"; if (str1 < str2) { trace("A < a, B < b, C < c, ..."); }
156
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Когда эти операторы используются со строками, код ActionScript рассматривает значение кода каждого символа в строке, сравнивая их слева направо, как показано ниже.
trace("A" < "B"); // true trace("A" < "a"); // true trace("Ab" < "az"); // true trace("abc" < "abza"); // true
Используйте операторы ==
и !=
для сравнения строк друг с другом и с другими типами объектов, как показано в следующем примере.
var str1:String = "1"; var str1b:String = "1"; var str2:String = "2"; trace(str1 == str1b); // true trace(str1 == str2); // false var total:uint = 1; trace(str1 == total); // true
Получение строковых представлений других объектов
Можно получить представление String для объекта любого типа. Для этого у всех объектов есть метод toString()
.
var n:Number = 99.47; var str:String = n.toString(); // str == "99.47"
При использовании оператора сцепления +
с комбинацией объектов String и нестроковых объектов, метод toString()
использовать не требуется. Подробные сведения о сцеплении см. в следующем разделе.
Глобальная функция String()
возвращает для данного объекта то же значение, что и для объекта, вызывающего метод toString()
.
Сцепление строк
Сцеплением строк называется последовательное объединение двух строк в одну. Например, для сцепления двух строк можно использовать оператор +
.
var str1:String = "green"; var str2:String = "ish"; var str3:String = str1 + str2; // str3 == "greenish"
Также для получение того же результата можно использовать оператор +=
, как в следующем примере.
var str:String = "green"; str += "ish"; // str == "greenish"
Кроме того, String включает метод concat()
, который можно использовать следующим образом.
157
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
var str1:String = "Bonjour"; var str2:String = "from"; var str3:String = "Paris"; var str4:String = str1.concat(" ", str2, " ", str3); // str4 == "Bonjour from Paris"
Если оператор +
(или +=
) используется для объединения объекта String и нестрокового объекта, ActionScript автоматически преобразует нестроковый объект в объект String, чтобы оценить выражение, как показано ниже.
var str:String = "Area = "; var area:Number = Math.PI * Math.pow(3, 2); str = str + area; // str == "Area = 28.274333882308138"
Однако слагаемые можно группировать с помощью круглых скобок, чтобы предоставить контекст для оператора +
, как в следующем примере.
trace("Total: $" + 4.55 + 1.45); // output: Total: $4.551.45 trace("Total: $" + (4.55 + 1.45)); // output: Total: $6
Поиск подстрок и шаблонов в строках
Подстроки — это последовательные символы в строке. Например, строка "abc"
имеет следующие подстроки: ""
, "a"
, "ab"
, "abc"
, "b"
, "bc"
, "c"
. Для нахождения подстрок в строке можно пользоваться методами ActionScript.
В ActionScript шаблоны определяются с помощью строк или регулярных выражений. Например, следующее регулярное выражение определяет конкретный шаблон: за буквами A, B и C следует цифра (косые черты являются разделителями в регулярных выражениях).
/ABC\d/
ActionScript включает методы для поиска шаблонов в строках и для замены найденных соответствий на замещающие подстроки. Эти методы описываются в последующих разделах.
Регулярные выражения позволяют определять довольно сложные шаблоны. Дополнительные сведения см. в разделе «Использование регулярных выражений» на странице 221.
Поиск подстроки по позиции символа
Методы substr()
и substring()
имеют много общего. Они оба возвращают подстроку заданной строки. Они оба принимают два параметра. В обоих методах первый параметр указывает позицию начального символа в данной строке. Однако в методе substr()
вторым параметром является length, содержащий длину возвращаемой подстроки, а в методе substring()
— параметр end, содержащий позицию символа в конце подстроки (который не включен в возвращаемую строку). В этом примере демонстрируется различие этих двух методов. var str:String = "Hello from Paris, Texas!!!"; trace(str.substr(11,15)); // output: Paris, Texas!!! trace(str.substring(11,15)); // output: Pari
Метод slice()
похож на метод substring()
. Когда в качестве параметров заданы неотрицательные целые числа, он работает практически так же. Однако метод slice()
может принимать в качестве параметров и отрицательные числа. В этом случае позиция символа считается от конца строки, как в следующем примере.
158
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
var str:String = "Hello from Paris, Texas!!!"; trace(str.slice(11,15)); // output: Pari trace(str.slice(-3,-1)); // output: !! trace(str.slice(-3,26)); // output: !!! trace(str.slice(-3,str.length)); // output: !!! trace(str.slice(-8,-3)); // output: Texas
В качестве параметров метода slice()
можно указать комбинацию из отрицательного и неотрицательного чисел.
Поиск позиции символа соответствующей подстроки
Методы indexOf()
и lastIndexOf()
можно использовать для поиска соответствующих подстрок в строке, как в следующем примере.
var str:String = "The moon, the stars, the sea, the land"; trace(str.indexOf("the")); // output: 10
Обратите внимание на то, что метод indexOf()
учитывает регистр.
Можно задать второй параметр, чтобы указать позицию индекса в строке, с которой следует начинать поиск, как показано ниже.
var str:String = "The moon, the stars, the sea, the land" trace(str.indexOf("the", 11)); // output: 21
Метод lastIndexOf()
находит последнее вхождение подстроки в строке.
var str:String = "The moon, the stars, the sea, the land" trace(str.lastIndexOf("the")); // output: 30
Если для метода lastIndexOf()
указать второй параметр, поиск выполняется начиная с заданной позиции в обратном порядке (справа налево).
var str:String = "The moon, the stars, the sea, the land" trace(str.lastIndexOf("the", 29)); // output: 21
Создание массива подстрок, разбитых на основе разделителей
С помощью метода split()
можно создать массив подстрок, разбитых на основе используемых символов-
разделителей. Например, строку, разделенную с помощью запятых или табуляции, можно разбить на несколько подстрок.
В следующем примере показано, как можно разбить массив на подстроки, используя в качестве разделителя амперсанд (&).
var queryStr:String = "first=joe&last=cheng&title=manager&StartDate=3/6/65"; var params:Array = queryStr.split("&", 2); // params == ["first=joe","last=cheng"]
Второй, необязательный параметр метода split()
определяет максимальный размер возвращаемого массива.
В качестве разделителя можно также использовать регулярное выражение. var str:String = "Give me\t5." var a:Array = str.split(/\s+/); // a == ["Give","me","5."]
Дополнительные сведения см. в разделе «Использование регулярных выражений» на странице 221 и в справочнике по языку ActionScript 3.0 и компонентам.
159
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Поиск шаблонов в строках и замена подстрок
Класс String включает следующие методы для работы с шаблонами в строках.
•
Методы match()
и search()
служат для поиска подстрок, соответствующих шаблону.
•
Метод replace()
служит для поиска подстрок, соответствующих шаблону, и их замены заданной подстрокой.
Эти методы описываются в последующих разделах.
Для определения шаблонов, используемых в этих методах, можно использовать строки или регулярные выражения. Дополнительные сведения о регулярных выражениях см. в разделе «Использование регулярных выражений» на странице 221.
Поиск соответствующих подстрок
Метод search()
возвращает позицию индекса первой подстроки, соответствующей заданному шаблону, как в следующем примере.
var str:String = "The more the merrier."; // (This search is case-sensitive.) trace(str.search("the")); // output: 9 Для определения шаблона соответствия можно использовать регулярные выражения, как показано ниже.
var pattern:RegExp = /the/i; var str:String = "The more the merrier."; trace(str.search(pattern)); // 0
Метод trace()
выдает значение 0, так как первый символ в строе имеет позицию индекса 0. В регулярном выражении устанавливается флаг i
, чтобы при поиске не учитывался регистр.
Метод search()
находит только одно соответствие и возвращает его начальную позицию индекса, даже если в регулярном выражении задан флаг g
(global).
В следующем примере показано более сложное регулярное выражение, позволяющее найти соответствие строки, заключенной в двойные кавычки.
var pattern:RegExp = /"[^"]*"/; var str:String = "The \"more\" the merrier."; trace(str.search(pattern)); // output: 4 str = "The \"more the merrier."; trace(str.search(pattern)); // output: -1 // (Indicates no match, since there is no closing double quotation mark.)
Метод match()
работает подобным образом. Он выполняет поиск соответствующей подстроки. Однако, когда в шаблоне регулярного выражения установлен флаг global, как в следующем примере, метод match()
возвращает массив соответствующих значений.
var str:String = "bob@example.com, omar@example.org"; var pattern:RegExp = /\w*@\w*\.[org|com]+/g; var results:Array = str.match(pattern);
Массиву result
присваивается следующее значение:
["bob@example.com","omar@example.org"]
Дополнительные сведения о регулярных выражениях см. в разделе «Использование регулярных выражений» на странице 221«Использование регулярных выражений» на странице 221.
160
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Замена совпавших подстрок
С помощью метода replace()
можно найти нужный шаблон в строке и заменить соответствия заданной замещающей строкой, как в следующем примере. var str:String = "She sells seashells by the seashore."; var pattern:RegExp = /sh/gi; trace(str.replace(pattern, "sch")); //sche sells seaschells by the seaschore. Обратите внимание, что в этом примере в совпавших строках не учитывается регистра, так как в регулярном выражении установлен флаг i
(
ignoreCase
), и делается несколько замен, так как установлен флаг g
(
global
). Дополнительные сведения см. в разделе «Использование регулярных выражений» на странице 221.
В замещающую строку можно включить следующие коды с $
. Вместо замещающего кода с $
вставляется замещающий текст, приведенный в следующей таблице.
Например, ниже показано применение замещающих кодов $2
и $1
, представляющих первую и вторую зарегистрированные совпавшие группы:
var str:String = "flip-flop"; var pattern:RegExp = /(\w+)-(\w+)/g; trace(str.replace(pattern, "$2-$1")); // flop-flip
Также можно использовать функцию в качестве второго параметра метода replace()
. Совпавший текст заменяется возвращенным значением функции.
var str:String = "Now only $9.95!"; var price:RegExp = /\$([\d,]+.\d+)+/i; trace(str.replace(price, usdToEuro)); function usdToEuro(matchedSubstring:String, capturedMatch1:String, index:int, str:String):String { var usd:String = capturedMatch1; usd = usd.replace(",", ""); var exchangeRate:Number = 0.853690; var euro:Number = parseFloat(usd) * exchangeRate; const euroSymbol:String = String.fromCharCode(8364); return euro.toFixed(2) + " " + euroSymbol; }
Код с $ Замещающий текст
$$
$
$&
Совпавшая подстрока.
$`
Часть строки, предшествующая совпавшей подстроке. В этом коде используется прямая левая одинарная кавычка (
`
), а не прямая одинарная кавычка (
'
) или левая фигурная кавычка (
'
).
$'
Часть строки, которая предшествует совпавшей подстроке. Этот код использует прямую одиночную кавычку (
' ).
$
n Зарегистрированное совпадение группы в скобках n, где n — это цифра от 1 до 9, а за $n не следует десятичное число. $
nn Зарегистрированное совпадение группы в скобках nn, где nn десятичное двузначное число (от 01 до 99). Если запись nn не определена, в качестве замещающего текста используется пустая строка. 161
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Когда в качестве второго параметра метода replace()
используется функция, ей передаются следующие аргументы:
•
Совпадающая часть строки.
•
Зарегистрированные совпадения группы. Количество переданных таким образом аргументов варьируется в зависимости от количества совпадений в скобках. Количество совпадений в скобках можно определить, проверив значение параметра arguments.length - 3
в коде функции.
•
Позиция в индексе в строке, где начинается совпадение. •
Строка полностью.
Перевод строк в верхний или нижний регистр
Как показано на следующем примере, методы
toLowerCase()
и toUpperCase()
переводят буквенные символы строки в нижний или верхний регистр соответственно.
var str:String = "Dr. Bob Roberts, #9." trace(str.toLowerCase()); // dr. bob roberts, #9. trace(str.toUpperCase()); // DR. BOB ROBERTS, #9.
После выполнения этих методов исходная строка остается без изменений. Чтобы преобразовать исходную строку, используйте следующий код:
str = str.toUpperCase();
Эти методы поддерживают расширенные символы, а не только a–z и A–Z.
var str:String = "José Barça"; trace(str.toUpperCase(), str.toLowerCase()); // JOSÉ BARÇA josé barça
Пример: ASCII-графика
Этот пример ASCII-графики демонстрирует ряд возможностей работы с классом String в ActionScript 3.0, включая следующее. •
Метод split()
класса String используется для получения значений из строки, разделенной символами (графическая информация в файле с разделителем-табуляцией).
•
Чтобы написать с большой буквы каждое слово в названиях изображений, используется несколько приемов манипуляции со строками, включая метод split()
, сцепление и извлечение части строки с помощью методов substring()
и substr()
.
•
Метод getCharAt()
используется для получения одного символа из строки (чтобы определить символ ASCII, соответствующий значению растрового изображения в оттенках серого).
•
Сцепление строк используется, чтобы построить ASCII-представление изображения символ за символом.
Термином ASCII-графика называется текстовое представление изображения, в котором рисунок выстраивается в виде сетки символов моноширинного шрифта, такого как Courier New. Ниже приводится пример ASCII-графики, созданный приложением. 162
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Версия изображения, созданного с помощью ASCII-графики, находится справа.
Получить файлы приложения для этого примера можно на странице www.adobe.com/go/learn_programmingAS3samples_flash_ru. Файлы приложения ASCIIArt находятся в папке Samples/AsciiArt. Приложение состоит из следующих файлов.
Получение значений, разделенных табуляцией
В этом примере используется общепринятая практика, при которой данные приложения хранятся отдельно от самого приложения. Таким образом, если данные изменяются (например, при добавлении другого изображения или при изменении названия изображения), не требуется повторно создавать SWF-файл. В этом случае метаданные изображения, включая название, URL-адрес файла с изображением и некоторые значения, используемые для манипуляций с изображением) хранятся в текстовом файле (файл txt/ImageData.txt в проекте). Ниже приводится содержимое текстового файла:
Файл Описание
AsciiArtApp.mxml
или
AsciiArtApp.fla
Основной файл приложения Flash (FLA) или Flex (MXML)
com/example/programmingas3/asciiArt/AsciiArtBuilder.as Класс, обеспечивающий основные функции приложения, включая извлечение метаданных изображения из текстового файла, загрузку изображений, управление процессом преобразования изображения в текст.
com/example/programmingas3/asciiArt/BitmapToAsciiConverter.as Класс, обеспечивающий метод parseBitmapData() для преобразования данных изображения в версию класса String.
com/example/programmingas3/asciiArt/Image.as Класс, представляющий загруженное растровое изображение.
com/example/programmingas3/asciiArt/ImageInfo.as Класс, представляющий метаданные для изображения ASCII-графики (например, название, URL-адрес файла с изображением и т.д.).
image/Папка, содержащая изображения, используемые приложением.
txt/ImageData.txt Текстовый файл с разделителем-табуляцией, содержащий сведения об изображениях, предназначенных для загрузки приложением.
163
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
FILENAMETITLEWHITE_THRESHHOLDBLACK_THRESHHOLD FruitBasket.jpgPear, apple, orange, and bananad810 Banana.jpgA picture of a bananaC820 Orange.jpgorangeFF20 Apple.jpgpicture of an apple6E10
Файл использует специальный формат с разделителем-табуляцией. Первая строка является строкой заголовка. Остальные строки содержат следующие денные для каждого растрового изображения, предназначенного для загрузки:
•
имя файла с растровым изображением;
•
отображаемое имя растрового изображения;
•
пороговые значения для белого и черного цветов в растровом изображении; это шестнадцатеричные значения, выше и ниже которых пиксел считается полностью белым или черным соответственно. Как только запускается приложение, класс AsciiArtBuilder загружает и анализирует содержимое текстового файла, чтобы создать «стопку» изображений для показа с использованием следующего кода из метода parseImageInfo()
класса AsciiArtBuilder:
var lines:Array = _imageInfoLoader.data.split("\n"); var numLines:uint = lines.length; for (var i:uint = 1; i < numLines; i++) { var imageInfoRaw:String = lines[i]; ... if (imageInfoRaw.length > 0) { // Create a new image info record and add it to the array of image info. var imageInfo:ImageInfo = new ImageInfo(); // Split the current line into values (separated by tab (\t) // characters) and extract the individual properties: var imageProperties:Array = imageInfoRaw.split("\t"); imageInfo.fileName = imageProperties[0]; imageInfo.title = normalizeTitle(imageProperties[1]); imageInfo.whiteThreshold = parseInt(imageProperties[2], 16); imageInfo.blackThreshold = parseInt(imageProperties[3], 16); result.push(imageInfo); } }
Все содержимое текстового файла добавлено в один экземпляр String, в свойство _imageInfoLoader.data
. С помощью метода split()
, в качестве параметра которого используется символ новой строки (
"\n"
) экземпляр String разбивается в массив (
lines
), элементы которого представляют собой отдельные строки текстового файла. Затем код использует цикл для обработки каждой строки (кроме первой, так как она включает только заголовки, а не содержимое). Внутри цикла еще раз используется метод split()
, чтобы разбить содержимое одной строки с целью получения группы значений (объект Array с именем imageProperties
). В этом случае в качестве параметра метода split()
используется символ табуляции (
"\t"
), так как значения в каждой строке разделяются символами табуляции.
164
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
Использование методов класса String для нормализации заголовков изображений
Одним из решений дизайна для этого приложения является отображение названий изображений с использованием стандартного формата англоязычных заголовков, в котором каждое слово пишется с большой буквы (за исключением немногих слов, на которые это правило не распространяется). Не ожидая, что текстовый файл содержит заголовки в правильном формате, приложение форматирует их в момент получения из текстового файла.
В предыдущем коде в процессе получения метаданных отдельного изображения используется следующая строка:
imageInfo.title = normalizeTitle(imageProperties[1]);
В этом коде заголовок изображения из текстового файла передается методу normalizeTitle()
и только после этого сохраняется в объекте ImageInfo.
private function normalizeTitle(title:String):String { var words:Array = title.split(" "); var len:uint = words.length; for (var i:uint; i < len; i++) { words[i] = capitalizeFirstLetter(words[i]); } return words.join(" "); }
Этот метод вызывает метод split()
для деления заголовка на несколько слов (разделенных пробелом), передает каждое слово методу capitalizeFirstLetter()
, а затем использует метод join()
класса Array для повторного объединения отдельных слов в строку.
Метод capitalizeFirstLetter()
делает первую букву слова заглавной.
165
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
/** * Capitalizes the first letter of a single word, unless it's one of * a set of words that are normally not capitalized in English. */ private function capitalizeFirstLetter(word:String):String { switch (word) { case "and": case "the": case "in": case "an": case "or": case "at": case "of": case "a": // Don't do anything to these words. break; default: // For any other word, capitalize the first character. var firstLetter:String = word.substr(0, 1); firstLetter = firstLetter.toUpperCase(); var otherLetters:String = word.substring(1); word = firstLetter + otherLetters; } return word; }
В английском языке в заголовках не пишутся с заглавной буквы следующие слова: «and», «the», «in», «an», «or», «at», «of» и «a». (Это упрощенная версия правила.) Следуя этой логике, код сначала использует инструкцию switch
, чтобы проверить, не является ли слово исключением и его не нужно писать с заглавной буквы. Если это так, код просто покидает инструкцию switch
. С другой стороны, если слово должно быть написано с заглавной буквы, выполняются следующие действия.
1
Первая буква слова извлекается с помощью метода substr(0, 1)
, который получает подстройку с начальным индексом символа 0 (первая буква в строке, на что указывает первый параметр 0
). Подстрока будет содержать один символ (о чем говорит второй параметр 1
).
2
Этот символ переводится в верхний регистр с помощью метода toUpperCase()
.
3
Остальные символы исходного слова извлекаются с помощью метода substring(1)
, который получает подстроку начиная с индекса 1 (вторая буква) до конца строки (на что указывает отсутствие второго параметра в методе substring()
).
4
Окончательная версия слова создается путем объединения заглавной первой буквы с остальными посредством сцепления строк: firstLetter + otherLetters
.
Создание текста ASCII-графики
Класс BitmapToAsciiConverter обеспечивает возможность преобразования растрового изображения в текстовое представление с использованием символов ASCII. Этот процесс выполняется методом parseBitmapData()
, фрагмент которого представлен ниже.
166
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа со строками
var result:String = ""; // Loop through the rows of pixels top to bottom: for (var y:uint = 0; y < _data.height; y += verticalResolution) { // Within each row, loop through pixels left to right: for (var x:uint = 0; x < _data.width; x += horizontalResolution) { ... // Convert the gray value in the 0-255 range to a value // in the 0-64 range (since that's the number of "shades of // gray" in the set of available characters): index = Math.floor(grayVal / 4); result += palette.charAt(index); } result += "\n"; } return result;
Сначала код определяет экземпляр String с именем result
, который будет использоваться для построения ASCII-графики для растрового изображения. Затем выполняется циклическая обработка отдельных пикселов исходного растрового изображения. Используя несколько приемов манипуляции с цветами (опущенных здесь для краткости), код преобразует значения красного, зеленого и синего цветов отдельного пиксела в одно значение оттенка серого (число от 0 до 255). После этого код делит это значение на 4 (как показано в примере), чтобы преобразовать его в диапазон 0-63, и сохраняет полученное число в переменной index
. (Используется диапазон от 0 до 63, так как «палитра» доступных символов ASCII, используемых этим приложением, составляет 64 значения.) Палитра символов определяется как экземпляр String в классе BitmapToAsciiConverter.
// The characters are in order from darkest to lightest, so that their // position (index) in the string corresponds to a relative color value // (0 = black). private static const palette:String = "@#$%&8BMW*mwqpdbkhaoQ0OZXYUJCLtfjzxnuvcr[]{}1()|/?Il!i><+_~-;,. ";
Переменная index
определяет, какой символ ASCII соответствует текущему пикселу растрового изображения, и требуемый символ извлекается из экземпляра String с именем palette
с помощью метода charAt()
. Затем он добавляется в экземпляр String с именем result
с помощью оператора сложения с присвоением (
+=
). Кроме того, в конце каждого ряда пикселов к экземпляру result
добавляется символ новой строки, чтобы перенести строку и начать новый ряд символов-«пикселов». 167
Глава 8. Работа с массивами
Массивы позволяют хранить множество значений в единой структуре данных. В простых индексных массивах значения сохраняются с помощью фиксированных порядковых целочисленных индексов, а в сложных ассоциативных массивах — с помощью произвольно задаваемых ключей. Массивы также могут иметь несколько измерений и содержать элементы, которые сами являются массивами. Наконец, для массива, элементы которого являются экземплярами одного типа данных, можно использовать Vector. В этой главе рассказывается, как создавать массивы разных типов и управлять ими.
Основные сведения о массивах
Введение в работу с массивами
В программировании нередко приходится работать не с одним объектом, а с группой элементов. Например, в приложении для воспроизведения музыки может потребоваться создать список песен, ожидающих своей очереди. Было бы затруднительно создавать отдельную переменную для каждой песни в списке. Желательно организовать все объекты Song в одну группу и работать с ними как с одним целым.
Массив — это элемент программирования, который выполняет функцию контейнера для набора элементов, такого как список песен. Чаще всего все элементы в массиве являются экземплярами одного класса, но это не является обязательным условием в ActionScript. Отдельные объекты в массиве называются его элементами. Массив можно представить себе как картотеку для переменных. Переменные можно добавлять в качестве элементов массива, наподобие добавления карточки в картотеку. Массив можно обрабатывать как одну переменную (как будто переставить всю картотеку в другое место). Переменные можно обрабатывать как группу (как будто искать нужную информацию, перебирая карточки). Также можно обращаться к ним в индивидуальном порядке (как будто открыть картотеку и достать из нее одну карточку).
Допустим, что вы создаете музыкальный проигрыватель, в котором пользователь может выбрать несколько песен и добавить их в список воспроизведения. В коде ActionScript есть метод addSongsToPlaylist()
, который принимает в качестве параметра один массив. Независимо от количества песен, которые нужно добавить в список (мало, много или всего одну), можно вызвать метод addSongsToPlaylist()
только один раз, передав ему массив с объектами Song. Внутри метода addSongsToPlaylist()
можно использовать цикл, который будет по одному проходить элементы массива (песни) и фактически добавлять их в список воспроизведения.
Самым распространенным типом массива ActionScript является индексный массив. В индексном массиве каждый элемент хранится в пронумерованном слоте (так называемом индексе). При обращении к элементам этот номер используется в качестве адреса. Индексные массивы подходят для большинства потребностей программирования. Класс Array — это один общий класс, используемый для представления индексного массива.
Нередко индексный массив используется для хранения нескольких элементов одного типа (объектов, являющихся экземплярами одного класса). Класс Array не имеет средств для ограничения типа содержащихся в нем элементов. Класс Vector представляет собой тип индексного массива, в котором все элементы принадлежат одному типу. Используя экземпляр Vector вместо экземпляра Array, можно повысить производительность и получить другие преимущества. Класс Vector доступен для использования, начиная с Flash Player версии 10 и Adobe AIR версии 1.5.
168
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Особым случаем использования индексного массива является многомерный массив. Многомерный массив — это индексный массив, элементами которого являются индексные массивы (которые, в свою очередь, содержат другие элементы). Другим типом массива является ассоциативный массив, который для идентификации отдельных элементов использует строковый ключ а не числовой индекс. В завершение, язык ActionScript 3.0 также включает класс Dictionary, который представляет собой словарь. Словарь — это массив, который позволяет использовать любой тип объекта в качестве ключа для идентификации элементов.
Общие задачи массивов
В данной главе описываются следующие действия с массивами:
•
создание индексных массивов с использованием классов Array и Vector;
•
добавление и удаление элементов массива;
•
сортировка элементов массива;
•
извлечение частей масива;
•
работа с ассоциативными массивами и словарями;
•
работа с многомерными массивами;
•
копирование элементов массива;
•
создание подкласса массива;
Важные понятия и термины
Ниже приводится список важных терминов, с которыми вы столкнетесь в этой главе.
•
Массив: объект, который служит контейнером для группировки нескольких объектов.
•
Оператор доступа к массиву (
[]
): пара квадратных скобок, в которые заключен индекс или ключ, являющийся уникальным идентификатором элемента массива. Этот синтаксис используется после имени переменной массива, чтобы указать не весь массив, а один из его элементов.
•
Ассоциативный массив: массив, использующий строковые ключи для идентификации отдельных элементов.
•
Базовый тип: тип данных для объектов, которые могут храниться в экземпляре Vector.
•
Словарь: массив, элементы которого состоят из пар объектов «ключ-значение». Ключ используется для идентификации одного объекта вместо числового индекса.
•
Элемент: один элемент в массиве.
•
Индекс: числовой «адрес», используемый для идентификации одного элемента в индексном массиве.
•
Индексный массив: стандартный тип массива, который сохраняет каждый элемент в пронумерованной позиции и использует этот номера (индексы) для идентификации отдельных элементов.
•
Ключ: строка или объект, используемый для идентификации одного элемента в ассоциативном массиве или словаре.
•
Многомерный массив: массив, содержащий элементы, которые являются массивами, а не одиночными значениями.
169
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
•
T
: стандартное сокращение, которое в данной документации обозначает базовый тип экземпляра Vector независимо от того, чем он представлен. Сокращение T служит для представления имени класса, как показано в описании параметра Type. («Т» обозначает «тип», как в словосочетании «тип данных».)
•
Параметр типа: синтаксис, который используется с именем класса Vector, чтобы указать его базовый тип (тип данных для сохраняемых объектов). Синтаксис содержит точку (
.
), затем следует имя типа данных в угловых скобках (
<>
). В общем параметр типа выглядит так: Vector.<T>
. В данной документации класс, указанный в параметре типа, представлен в общем виде: T
.
•
Vector: тип массива, все элементы которого относятся к одному типу данных.
Работа с примерами из главы
Прорабатывая главу, вы можете самостоятельно тестировать приведенные в ней примеры кодов. Важно, что все примеры кода в этой главе включают вызов соответствующей функции trace()
. Для тестирования кодов, приведенных в этой главе, выполните следующие действия.
1
Создайте пустой документ в инструменте разработки Flash.
2
Выберите ключевой кадр на временной шкале.
3
Откройте панель «Действия» и скопируйте код на панель «Сценарий».
4
Запустите программу, выбрав «Управление» > «Тестировать ролик».
Результаты функции trace()
отобразятся на панели «Вывод».
Этот и другие способы проверки примеров кода подробно описаны в разделе «Тестирование примеров кода» на странице 38.
Индексные массивы
В индексных массивах хранится последовательность из одного или более значений, организованных таким образом, чтобы каждое значение было доступно через целое число без знака. Первый индекс всегда равен 0, а затем для каждого последующего элемента массива он увеличивается на 1. В ActionScript 3.0 в качестве индексных массивов используются два класса: Array и Vector.
В индексных массивах в качестве индекса используется целое 32-разрядное число без знака. Максимальный размер индексного массива равен 2
32
- 1 или 4 294 967 295. При попытке создать массив, превышающий максимально допустимый размер, произойдет ошибка при выполнении.
Для обращения к отдельному элементу индексного массива служит оператор доступа к массиву (
[]
), который позволяет указать позицию индекса для требуемого элемента. Например, следующий код представляет первый элемент (с индексом 0) в индексном массиве с именем songTitles
.
songTitles[0]
Имя переменной массива, за которым следует индексом в квадратных скобках, выполняет роль уникального идентификатора элемента. (Другими словами, его можно использовать так же, как имя переменной.) Элементу индексного массива можно присвоить значение, используя имя и индекс в левой части инструкции присвоения.
songTitles[1] = "Symphony No. 5 in D minor";
Подобным образом можно получить значение элемента индексного массива, используя имя и индекс в правой части инструкции присвоения.
170
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
var nextSong:String = songTitles[2];
Также в квадратных скобках можно использовать переменную вместо конкретного значения. (Переменная должна содержать неотрицательное целое число, например беззнаковое целое число, положительное целое число или экземпляр Number, представленный положительным целым числом.) Этот прием обычно используется для циклического прохождения элементов индексного массива и выполнения операции над некоторыми или всеми элементами. Следующий код демонстрирует этот прием. Код создает цикл для обращения к каждому значению в объекте Array с именем oddNumbers
. Инструкция trace()
используется для вывода каждого значения в следующем виде: «oddNumber[index] = value».
var oddNumbers:Array = [1, 3, 5, 7, 9, 11]; var len:uint = oddNumbers.length; for (var i:uint = 0; i < len; i++) { trace("oddNumbers[" + i.toString() + "] = " + oddNumbers[i].toString()); }
Класс Array
Первый тип индексного массива представлен классом Array. Экземпляр Array может содержать значение данных любого типа. Один объект Array может содержать объекты, представленные разными типами данных. Например, один экземпляр Array может содержать значение String в позиции индекса 0, экземпляр Number в позиции 1 и объект XML в позиции 2.
Класс Vector
Другой тип индексного массива, поддерживаемый в ActionScript 3.0, представлен классом Vector. Экземпляр Vector — это типизированный массив, то есть все элементы в экземпляре Vector всегда имеют одинаковый тип данных.
Примечание. Класс Vector доступен для использования, начиная с Flash Player версии 10 и Adobe AIR версии 1.5.
Когда объявляется переменная Vector или создается экземпляр Vector, необходимо четко указать тип данных для объектов, которые может содержать Vector. Указанный тип данных называется базовым типом объекта Vector. Во время выполнения и компиляции (в строгом режиме) проверяется любой код, задающий или получающий значение элемента Vector. Если тип данных добавляемого или получаемого объекта не соответствует базовому типу Vector, выдается ошибка.
Помимо ограничения, связанного с типом данных, класс Vector имеет другие ограничения, которые отличают его от класса Array:
•
Вектор принадлежит к числу плотных массивов. Объект Array может иметь значения в позициях индекса 0 и 7, даже если нет значений в позициях с 1 по 6. Экземпляр Vector, напротив, должен иметь значение (или null
) в каждой позиции индекса.
•
По желанию можно ограничить длину объекта Vector. Это значит, что количество элементов в массиве Vector не может изменяться.
•
Доступ к элементам вектора осуществляется с контролем границ. Вам никогда не удастся прочесть значение с индексом, превышающим индекс финального элемента (
length
— 1). Вам также не удастся задать значение, индекс которого превышает текущий последний индекс (иначе говоря, значение можно присваивать только с существующим индексом или с индексом [length]
).
В результате этих ограничений экземпляр Vector имеет два основных преимущества перед экземпляром Array, все элементы которого представляют собой экземпляры одного класса:
•
Производительность: доступ к массиву и итерация осуществляются гораздо быстрее при использовании экземпляра Vector, чем при использовании экземпляра Array.
171
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
•
Безопасность типа: в строгом режиме компилятор может выявлять ошибки, связанные с типом данных. К таким ошибкам относится присвоение экземпляру Vector значения неверного типа данных или попытка получить неверный тип данных при считывании значения из объекта Vector. Во время выполнения типы данных также проверяются при записи или чтении данных в объекте Vector. Однако следует учесть, что при использовании метода push()
или unshift()
для добавления значений в вектор типы данных для аргументов не проверяются во время компиляции. Тем не менее, при использовании этих методов значения проверяются во время выполнения.
Если опустить дополнительные ограничения и преимущества, класс Vector очень похож на класс Array. Свойства и методы объекта Vector похожи (и в большинстве случаев идентичны) свойствам и методам объекта Vector. В любом случае, когда используется объект Array, все элементы которого относятся к одному и тому же типу данных, предпочтительным является экземпляр Vector.
Создание массивов
Создавать экземпляры Array и Vector можно разными способами. Однако приемы, используемые для создания массива каждого типа, немного отличаются.
Создание экземпляра Array
Чтобы создать объект Array, нужно вызвать конструктор Array()
или использовать синтаксис литерала Array.
Существует три способа использования функции конструктора Array()
. Во-первых, можно вызвать конструктор без аргументов для создания пустого массива. Свойство length
класса Array используется для проверки отсутствия элементов в массиве. Например, приведенный ниже код вызывает конструктор Array()
без аргументов:
var names:Array = new Array(); trace(names.length); // output: 0
Во-вторых, если число является единственным параметром, который передается конструктору Array()
, создается массив именно этой величины, а каждому элементу задается значение undefined
. Аргументом должно быть целое число без знака от 0 до 4 294 967 295. Например, приведенный ниже код вызывает конструктор Array()
, единственным аргументом которого является число:
var names:Array = new Array(3); trace(names.length); // output: 3 trace(names[0]); // output: undefined trace(names[1]); // output: undefined trace(names[2]); // output: undefined
В-третьих, если вызвать конструктор и передать в качестве параметров список элементов, будет создан массив, элементы которого будут соответствовать этим параметрам. Приведенный ниже код передает три аргумента конструктору Array()
:
var names:Array = new Array("John", "Jane", "David"); trace(names.length); // output: 3 trace(names[0]); // output: John trace(names[1]); // output: Jane trace(names[2]); // output: David
Массивы также можно создавать с помощью литералов Array. Литерал Array можно назначить непосредственно переменной массива, как показано ниже:
var names:Array = ["John", "Jane", "David"];
172
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Создание экземпляра Vector
Чтобы создать экземпляр Vector, нужно вызвать конструктор Vector.<T>()
. Также для создания объекта Vector можно вызвать глобальную функцию Vector.<T>()
. Эта функция преобразует указанный объект в экземпляр Vector. В языке ActionScript нет эквивалента синтаксису литерала Array.
Каждый раз при объявлении переменной Vector (а также параметра метода или типа возвращаемых данных метода класса Vector) необходимо указывать ее базовый тип. Кроме того, базовый тип необходимо указывать при создании экземпляра Vector с помощью конструктора Vector.<T>()
. Другими словами, каждый раз при использовании термина Vector
в коде ActionScript он сопровождается указанием базового типа.
Базовый тип указывается с помощью синтаксиса параметра типа. В коде параметр типа следует непосредственно за словом Vector
. Он состоит из точки (
.
) и имени базового класса, заключенного в угловые скобки (
<>
), как показано в следующем примере:
var v:Vector.<String>; v = new Vector.<String>();
В первой строке примера переменная v
объявлена как экземпляр Vector.<String>
. Иначе говоря, он представляет индексный массив, который может содержать только экземпляры класса String. Вторая строка вызывает конструктор Vector()
для создания экземпляра того же типа Vector (то есть массив Vector, все элементы которого являются объектами String). Этот объект присваивается переменной v
.
Использование конструктора Vector.<T>()
Если конструктор Vector.<T>()
используется без аргументов, он создает пустой экземпляр Vector. Чтобы убедиться в том, что экземпляр Vector пуст, нужно проверить свойство length
. Например, следующий код вызывает конструктор Vector.<T>()
без аргументов.
var names:Vector.<String> = new Vector.<String>(); trace(names.length); // output: 0
Если заранее известно, сколько элементов изначально должен иметь экземпляр Vector, можно предварительно определить количество элементов в Vector. Чтобы создать экземпляр Vector с требуемым числом элементов, передайте это число в качестве первого параметра (свойство length
). Так как элементы объекта Vector не могут быть пустыми, они заполняются экземплярами базового типа. Если базовый тип является ссылочным типом, который допускает значения null
, то все элементы будут содержать значения null
. В противном случае все элементы содержат значения по умолчанию для базового класса. Например, переменная, выраженная беззнаковым целым числом, не может иметь значение null
. Поэтому в следующем коде экземпляр Vector с именем ages
создается с семью элементами, которые имеют значение 0.
var ages:Vector.<uint> = new Vector.<uint>(7); trace(ages); // output: 0,0,0,0,0,0,0 И, наконец, с помощью конструктора Vector.<T>()
также можно создавать объекты Vector с фиксированной длиной, передав значение true
для второго параметра (свойство fixed
). В этом случае экземпляр Vector создается с указанным числом элементов, которое нельзя изменить. Однако следует учесть, что при этом все равно можно изменять значения элементов объекта Vector с фиксированной длиной.
В отличие от класса Array, конструктору Vector.<T>()
нельзя передать начальные значения элементов экземпляра Vector.
173
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Использование глобальной функции Vector.<T>()
Помимо конструктора Vector.<T>()
для создания объекта Vector можно использовать глобальную функцию Vector.<T>()
. Глобальная функция Vector.<T>()
представляет собой функцию преобразования. Вызывая глобальную функцию Vector.<T>()
, нужно указать базовый тип объекта Vector, возвращаемого методом. В качестве аргумента передается один индексный массив (экземпляр Array или Vector). Затем метод возвращает объект Vector с заданным базовым типом, содержащий значения в аргументе исходного массива. В следующем коде показан синтаксис для вызова глобальной функции Vector.<T>()
.
var friends:Vector.<String> = Vector.<String>(["Bob", "Larry", "Sarah"]);
Глобальная функция Vector.<T>()
выполняет преобразования типа данных на двух уровнях. Во-первых, когда функции передается экземпляр Array, возвращается экземпляр Vector. Во-вторых, независимо от типа исходного массива (экземпляр Array или Vector) функция пытается преобразовать элементы исходного массива в значения базового типа. В ходе этого процесса используются стандартные правила преобразования типа данных ActionScript. Например, следующий код преобразует значения String исходного экземпляра Array в целые числа для полученного массива Vector. Десятичная запятая первого значения (
"1.5"
) усекается, а нечисловое третье значение (
"Waffles"
) преобразуется в 0.
var numbers:Vector.<int> = Vector.<int>("1.5", "17", "Waffles"]); trace(numbers); // output: 1,17,0
Если не удается преобразовать ни один из элементов, выдается ошибка.
Если при вызове глобальной функции Vector.<T>()
элемент в исходном массиве является экземпляром подкласса указанного базового типа, этот элемент добавляется в полученный объект Vector (ошибка не выдается). Использование глобальной функции Vector.<T>()
фактически является единственным способом преобразования объекта Vector с базовым типом T
в Vector с базовым типом, который является суперклассом T
.
Вставка элементов массива
Самым простым способом добавления элемента в индексный массив является использование оператора доступа к массиву (
[]
). Чтобы задать значение для элемента индексного массива, используйте имя объекта Array или Vector и индекс в левой части инструкции присвоения.
songTitles[5] = "Happy Birthday";
Если в объекте Array или Vector еще нет элемента с таким индексом, он создается и используется для сохранения нового значения. Если в данной позиции индекса уже существует значение, оно заменяется новым значением.
Объект Array позволяет создавать элементы в любой позиции индекса. А в объекте Vector, напротив, значение можно присваивать только существующему индекса или следующему за ним. Следующий доступный индекс соответствует свойству length
объекта Vector. Самым безопасным способом добавления нового элемента в объект Vector является использование кода, подобного следующему:
myVector[myVector.length] = valueToAdd;
Три метода классов Array и Vector: push()
, unshift()
и splice()
— позволяют вставлять элементы в индексный массив. Метод push()
добавляет один или несколько элементов в конец массива. Иными словами, у последнего элемента, вставленного в массив с помощью метода push()
, будет наибольший индекс. Метод unshift()
вставляет один или более элементов в начало массива, при этом первый индекс всегда равен 0. Метод splice()
вставляет любое число элементов по заданному индексу в массиве.
174
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
В следующем примере показаны все три метода: Массив с именем planets
создается для хранения названий планет в порядке удаленности от Солнца. Сначала вызывается метод push()
и создается первый элемент Mars
. Затем вызывается метод unshift()
и вставляет в начало массива элемент Mercury
. Наконец, вызывается метод splice()
и вставляет элементы Venus
и Earth
после Mercury
и перед Mars
. Первый аргумент, передаваемый методу splice()
, — это целое число 1. Он указывает, что вставку необходимо производить после индекса 1. Второй аргумент, передаваемый методу splice()
, — это целое число 0. Он указывает, что никакие элементы удалять не нужно. Наконец, третий и четвертый аргументы — Venus
и Earth
, передаваемые методу splice()
, — это вставляемые элементы. var planets:Array = new Array(); planets.push("Mars"); // array contents: Mars planets.unshift("Mercury"); // array contents: Mercury,Mars planets.splice(1, 0, "Venus", "Earth"); trace(planets); // array contents: Mercury,Venus,Earth,Mars
Методы push()
и unshift()
возвращают целое число без знака, обозначающее величину измененного массива. Когда для вставки элементов используется метод splice()
, он возвращает пустой массив. Это может показаться странным, но с учетом богатых возможностей применений метода splice()
это вполне оправданно. Метод splice()
можно использовать не только для вставки элементов в массив, но и для их удаления из массива. Когда метод splice()
используется для удаления элементов, он возвращает массив удаленных элементов.
Примечание. Если свойство fixed
объекта Vector имеет значение true
, общее число элементов в массиве нельзя изменить. Если попытаться добавить новый элемент в объект Vector с фиксированной длиной с помощью описанных здесь приемов, произойдет ошибка.
Получение значений и удаление элементов массива
Самый простой способ получить значение элемента индексного массива — использовать оператор доступа к массиву (
[]
). Чтобы получить значение для элемента индексного массива, используйте имя объекта Array или Vector и индекс в правой части инструкции присвоения.
var myFavoriteSong:String = songTitles[3];
Также можно попытаться получить значение из объекта Array или Vector, используя позицию индекса, в которой нет элемента. В этом случае объект Array возвращает значение undefined, а объект Vector выдает исключение RangeError.
Три метода классов Array и Vector: pop()
, shift()
и splice()
— позволяют удалять элементы. Метод pop()
удаляет элемент из конца массива. Иначе говоря, он удаляет элемент с наибольшим индексом. Метод shift()
удаляет элемент из начала массива, т.е. каждый раз удаляется элемент с индексом 0. Метод splice()
, который также может использоваться для вставки элементов, удаляет произвольное число элементов, начиная с индекса, заданного первым из передаваемых методу аргументов.
В примере ниже показано использование всех трех методов для удаления элементов из экземпляра Array. Массив Array с именем oceans
создается для хранения названий океанов. Некоторые из названий в массиве — это озера, а не океаны, и их нужно удалить. Во-первых, используем метод splice()
для удаления элементов Aral
и Superior
и вставки элементов Atlantic
и Indian
. Первый аргумент, передаваемый методу splice()
, — это целое число 2. Он указывает, что операцию необходимо начинать с третьего элемента в списке, т.е. элемента с индексом 2. Второй аргумент, 2, указывает, что нужно удалить два элемента. Остальные аргументы: Atlantic
и Indian
— это значения, которые нужно вставить после индекса 2. 175
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Во-вторых, используем метод pop()
для удаления последнего элемента массива — Huron
. B-третьих, используем метод shift()
для удаления первого элемента массива — Victoria
.
var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian", "Huron"]; oceans.splice(2, 2, "Arctic", "Atlantic"); // replaces Aral and Superior oceans.pop(); // removes Huron oceans.shift(); // removes Victoria trace(oceans);// output: Pacific,Arctic,Atlantic,Indian
Методы pop()
и shift()
возвращают элемент, который был удален. Для объекта Array, типом данных возвращаемого значения является Object, так как массивы могут содержать данные любого типа. Для объекта Vector типом данных возвращаемого значения является его базовый класс. Метод splice()
возвращает объект Array или Vector с удаленными значениями. Можно изменить пример с массивом oceans
так, чтобы вызов метода splice()
назначал возвращенный объект Array новой переменной Array, как показано ниже:
var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic"); trace(lakes); // output: Aral,Superior
Вам может встретиться код, применяющий оператор delete
к элементу объекта Array. Оператор delete
задает элементу объекта Array значение undefined
, но не удаляет его из массива. Например, в приведенном ниже коде оператор delete
применяется к третьему элементу массива oceans
, но длина объекта Array по-
прежнему остается равной 5.
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"]; delete oceans[2]; trace(oceans);// output: Arctic,Pacific,,Indian,Atlantic trace(oceans[2]); // output: undefined trace(oceans.length); // output: 5
Можно усечь экземпляр Array или Vector с помощью свойства length
. Если задать свойству length
индексного массива значение меньше текущей длины, массив будет усечен, и все элементы с индексами больше нового значения length
минус 1 будут удалены. Например, если массив oceans отсортировать так, чтобы все нужные значения были в начале массива, то с помощью свойства length
можно удалить записи в конце массива, как показано ниже:
var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"]; oceans.length = 2; trace(oceans); // output: Arctic,Pacific
Примечание. Если свойство fixed
объекта Vector имеет значение true
, общее число элементов в массиве нельзя изменить. Если попытаться удалить элемент или усечь экземпляр Vector с фиксированной длиной с помощью описанных здесь приемов, произойдет ошибка.
Сортировка массива
Существует три метода: reverse()
, sort()
и sortOn()
, — позволяющих изменить порядок элементов в индексном массиве путем сортировки или задания обратного порядка. Все они изменяют имеющийся массив. В следующей таблице приводятся общие сведения об этих методах и их поведении для объектов Array и Vector.
176
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Метод reverse()
Метод reverse()
не принимает никаких параметров и не возвращает значений, но позволяет переключать порядок массива с прямого на обратный. В следующем примере порядок океанов в массиве oceans
меняется с прямого на обратный:
var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"]; oceans.reverse(); trace(oceans); // output: Pacific,Indian,Atlantic,Arctic
Базовая сортировка с помощью метода sort() (только для класса Array)
Для класса Array метод sort()
меняет порядок элементов в массиве с помощью порядка сортировки по умолчанию. Порядок сортировки по умолчанию обладает определенными характеристиками. Они перечислены ниже.
•
Сортировка чувствительна к регистру, поэтому заглавные буквы всегда имеют приоритет перед строчными. Например, буква «D» предшествует букве «b». •
Сортировка выполняется по возрастанию, т.е. символы с меньшей величиной кода (скажем, «A») предшествуют символам с большей (скажем, «B»).
•
Одинаковые значения располагаются друг за другом, но определенного порядка внутри них самих нет.
•
В основе сортировки лежат строки, так как элементы перед сравнением преобразуются в строки (например, «10» предшествует «3», потому что строка "1"
имеет меньшую величину кода символа, чем "3"
). Вам может потребоваться отсортировать массив без учета регистра или в порядке убывания, а может быть, массив содержит числа, которые вы хотите отсортировать по величине, а не в алфавитном порядке. У метода sort()
класса Array есть параметр options
, позволяющий изменять каждую из характеристик порядка сортировки по умолчанию. Характеристики определяются набором статических переменных в классе Array, как показано ниже.
•
Array.CASEINSENSITIVE
отменяет чувствительность к регистру. В этом случае, например, строчная буква «b» будет предшествовать заглавной «D».
•
Array.DESCENDING
изменяет возрастающий порядок сортировки по умолчанию на убывающий. Например, буква «В» предшествует букве «А».
•
Array.UNIQUESORT
останавливает сортировку, если обнаруживаются два одинаковых значения.
•
Array.NUMERIC
позволяет выполнять сортировку чисел по величине, так чтобы число 3 стояло перед числом 10.
В примере ниже некоторые из этих параметров освещены подробнее: Создается объект Array с именем poets
, который сортируется с помощью нескольких разных параметров.
Метод Поведение Array Поведение Vector
reverse()
Изменяет порядок элементов таким образом, что последний элемент становится первым, предпоследний — вторым и так далее.
То же, что для объекта Array
sort()
Позволяет сортировать элементы объекта Array разными предварительно определенными способами, например в алфавитном порядке или по номерам. Также можно задать пользовательский алгоритм сортировки
Сортирует элементы в соответствии с алгоритмом сортировки, определенным пользователем.
sortOn()
Позволяет сортировать объекты, которые имеют одно или несколько общих свойств, указав одно или более свойств в качестве критериев сортировки.
Не доступен для класса Vector
177
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
var poets:Array = ["Blake", "cummings", "Angelou", "Dante"]; poets.sort(); // default sort trace(poets); // output: Angelou,Blake,Dante,cummings poets.sort(Array.CASEINSENSITIVE); trace(poets); // output: Angelou,Blake,cummings,Dante poets.sort(Array.DESCENDING); trace(poets); // output: cummings,Dante,Blake,Angelou poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // use two options trace(poets); // output: Dante,cummings,Blake,Angelou
Пользовательская сортировка с помощью метода sort() (для классов Array и Vector)
Помимо базовой сортировки, доступной для объектов Array, также можно определить пользовательское правило сортировки. Этот прием является единственной формой использования метода sort()
для класса Vector. Чтобы определить собственный порядок сортировки, нужно написать пользовательскую функцию сортировки и передать ее в качестве аргумента методу sort()
.
Например, если у вас есть список имен, каждый из элементов которого состоит из имени и фамилии, а вы хотите отсортировать его по фамилиям, используйте собственную функцию сортировки для разбора каждого элемента и выполнения сортировки по фамилии. В примере ниже показано, как это сделать с помощью собственной функции, которая является параметром метода Array.sort()
:
var names:Array = new Array("John Q. Smith", "Jane Doe", "Mike Jones"); function orderLastName(a, b):int { var lastName:RegExp = /\b\S+$/; var name1 = a.match(lastName); var name2 = b.match(lastName); if (name1 < name2) { return -1; } else if (name1 > name2) { return 1; } else { return 0; } } trace(names); // output: John Q. Smith,Jane Doe,Mike Jones names.sort(orderLastName); trace(names); // output: Jane Doe,Mike Jones,John Q. Smith
Персонализированная функция сортировки orderLastName()
использует регулярное выражение для извлечения фамилии из каждого элемента и сравнения значений по фамилиям. Идентификатор функции orderLastName
используется как самостоятельный параметр при вызове метода sort()
в массиве names
. Функция сортировки принимает два параметра, a
и b
, потому что она обрабатывает два элемента одновременно. Значение, возвращаемое функцией сортировки, указывает, каким образом сортировать элементы:
•
Возвращенное значение -1 означает, что первый параметр, a
, стоит перед вторым, b
. 178
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
•
Возвращенное значение 1 указывает, что второй параметр, b
, стоит перед первым, a
. •
Возвращенное значение 0 говорит о том, что элементы равны в контексте сортировки. Метод sortOn() (только для класса Array)
Метод sortOn()
разработан для объектов Array с элементами, содержащими объекты. У этих объектов должно быть хотя бы одно общее свойство, которое можно использовать в качестве ключа сортировки. Использование метода sortOn()
в массивах любого другого типа возвращает непредсказуемые результаты.
Примечание. Класс Vector не имеет метода sortOn()
. Он доступен только для объектов Array.
В примере ниже объект Array с именем poets
преобразуется, и каждый элемент превращается из строки в объект. Каждый объект содержит фамилию поэта и год его рождения.
var poets:Array = new Array(); poets.push({name:"Angelou", born:"1928"}); poets.push({name:"Blake", born:"1757"}); poets.push({name:"cummings", born:"1894"}); poets.push({name:"Dante", born:"1265"}); poets.push({name:"Wang", born:"701"});
Метод sortOn()
можно использовать для сортировки объекта Array по свойству born
. Метод sortOn()
определяет два параметра: fieldName
и options
. Аргумент fieldName
должен быть строкой. В примере ниже вызывается метод sortOn()
с двумя аргументами "born"
и Array.NUMERIC
. Аргумент Array.NUMERIC
используется для гарантии того, что сортировка выполняется по величине чисел, а не по алфавиту. Следует придерживаться этого способа, даже если все числа одного порядка, потому что, если добавятся числа меньшего или большего порядков, вы будете точно знать, что сортировка будет выполняться правильно.
poets.sortOn("born", Array.NUMERIC); for (var i:int = 0; i < poets.length; ++i) { trace(poets[i].name, poets[i].born); } /* output: Wang 701 Dante 1265 Blake 1757 cummings 1894 Angelou 1928 */
Сортировка без изменения исходного массива (только для класса Array)
Как правило, методы sort()
и sortOn()
вносят изменения в объект Array. Если требуется выполнить сортировку без изменения существующего объекта Array, передайте константу Array.RETURNINDEXEDARRAY
как часть параметра options
. Этот параметр указывает методам, что нужно возвратить новый объект Array с сортировкой и оставить существующий массив без изменений. Методы возвращают простой массив индексов, отражающий новый порядок сортировки и не содержащий элементов исходного объекта Array. Например, для сортировки массива poets
по году рождения без изменения самого объекта Array константа Array.RETURNINDEXEDARRAY
включается как часть аргумента, передаваемого для параметра options
. В примере ниже возвращенная информация об индексах сохраняется в объекте Array с именем indices
, а затем массив indices
используется вместе с исходным массивом poets
, чтобы вывести имена поэтов в порядке их годов рождения.
179
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
var indices:Array; indices = poets.sortOn("born", Array.NUMERIC | Array.RETURNINDEXEDARRAY); for (var i:int = 0; i < indices.length; ++i) { var index:int = indices[i]; trace(poets[index].name, poets[index].born); } /* output: Wang 701 Dante 1265 Blake 1757 cummings 1894 Angelou 1928 */
Запросы в массив
Четыре метода классов Array и Vector: concat()
, join()
, slice()
, toString()
— отправляют запросы в массив, но не изменяют его. Методы concat()
и slice()
возвращают новые массивы, а методы join()
и toString()
возвращают строки. Метод concat()
принимает в качестве аргументов новый массив или список элементов и совмещает его с предыдущим массивом для создания нового. У метода slice()
есть два параметра с говорящими названиями startIndex
и endIndex
. Этот метод возвращает новый массив, содержащий копии элементов, «вырезанных» из существующего массива. Вырезаемый фрагмент начинается с элемента с индексом startIndex
и заканчивается перед элементом endIndex
. Еще раз отметим, что элемент с индексом endIndex
не включается в возвращаемые значения.
В следующем примере методы concat()
и slice()
используются для создания новых массивов с помощью элементов других массивов:
var array1:Array = ["alpha", "beta"]; var array2:Array = array1.concat("gamma", "delta"); trace(array2); // output: alpha,beta,gamma,delta var array3:Array = array1.concat(array2); trace(array3); // output: alpha,beta,alpha,beta,gamma,delta var array4:Array = array3.slice(2,5); trace(array4); // output: alpha,beta,gamma
Методы join()
и toString()
можно использовать для отправки запросов в массив и возвращения его содержимого в виде строки. Если в методе join()
не используются никакие параметры, оба метода ведут себя одинаково и возвращают строку, содержащую все элементы массива, разделенные запятыми. Метод join()
, в отличие от метода toString()
, принимает параметр delimiter
, позволяющий выбрать знак для отделения элементов возвращаемой строки друг от друга.
В примере ниже создается объект Array с именем rivers
, затем вызываются методы join()
и toString()
для возвращения значений массива в виде строки. Метод toString()
возвращает значения, разделенные запятой (
riverCSV
), в то время как метод join()
возвращает значения, разделенные знаком +
.
var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"]; var riverCSV:String = rivers.toString(); trace(riverCSV); // output: Nile,Amazon,Yangtze,Mississippi var riverPSV:String = rivers.join("+"); trace(riverPSV); // output: Nile+Amazon+Yangtze+Mississippi
180
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
При работе с методом join()
необходимо помнить, что он всегда возвращает вложенные экземпляры Array или Vector со значениями, разделенными запятой, вне зависимости от того, какой разделительный знак вы задали для основных элементов массива. Это проиллюстрировано в примере:
var nested:Array = ["b","c","d"]; var letters:Array = ["a",nested,"e"]; var joined:String = letters.join("+"); trace(joined); // output: a+b,c,d+e
Ассоциативные массивы
Ассоциативный массив, иногда называемый хеш-таблицей или сопоставлением, использует для организации хранимых значений ключи вместо числовых индексов. Каждый ключ в ассоциативном массиве — это уникальная строка, используемая для доступа к хранимому значению. Ассоциативный массив — это экземпляр класса Object, то есть каждый ключ соответствует имени свойства. Ассоциативные массивы — это неупорядоченные наборы пар «ключ-значение». Ключи в ассоциативном массиве не подчиняются какому-
либо порядку. В ActionScript 3.0 также предусмотрен расширенный тип ассоциативного массива под названием словарь. Словари являются экземплярами класса Dictionary в пакете flash.utils и используют ключи, которые могут быть любым типом данных. Иными словами, ключи словаря не ограничиваются значениями типа String. Ассоциативные массивы со строками-ключами
В ActionScript 3.0 ассоциативные массивы можно создавать двумя способами. Во-первых, можно использовать экземпляр Object. С помощью экземпляра Object можно инициализировать массив, используя литерал объекта. Экземпляр класса Object, также называемый родовым объектом, по своим функциям идентичен ассоциативному массиву. Имя каждого из свойств родового объекта служит ключом доступа к сохраненному значению. В примере ниже показано, как создавать ассоциативный массив monitorInfo
с помощью литерала объекта, чтобы инициализировать массив с двумя парами «ключ-значение».
var monitorInfo:Object = {type:"Flat Panel", resolution:"1600 x 1200"}; trace(monitorInfo["type"], monitorInfo["resolution"]); // output: Flat Panel 1600 x 1200
Если вам не нужно инициализировать массив во время объявления, можно использовать для создания массива конструктор Object, как показано ниже:
var monitorInfo:Object = new Object();
После создания массива с помощью литерала объекта или конструктора класса Object можно добавить к массиву новые значения либо с помощью оператора доступа к массиву (
[]
, либо с помощью оператора «точка» (
.
). В примере ниже показано, как добавить два новых значения в массив monitorArray
:
monitorInfo["aspect ratio"] = "16:10"; // bad form, do not use spaces monitorInfo.colors = "16.7 million"; trace(monitorInfo["aspect ratio"], monitorInfo.colors); // output: 16:10 16.7 million
Обратите внимание, что ключ aspect ratio
содержит символ пробела. При использовании с оператором доступа к массиву (
[]
) это допустимо, но при использовании с оператором «точка» приведет к ошибке. Использовать пробелы в именах ключей не рекомендуется.
181
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Второй способ создать ассоциативный массив — использовать конструктор Array (или конструктор любого динамического класса), а затем использовать оператор доступа к массиву (
[]
) или «точка» (
.
) для добавления пар «ключ-значение» в массив. Если вы объявляете ассоциативный массив как массив любого типа класса Array, нельзя использовать для инициализации массива литерал объекта. В примере ниже показано, как создать ассоциативный массив monitorInfo
с помощью конструктора Array и добавить ключ type
и ключ resolution
вместе со значениями:
var monitorInfo:Array = new Array(); monitorInfo["type"] = "Flat Panel"; monitorInfo["resolution"] = "1600 x 1200"; trace(monitorInfo["type"], monitorInfo["resolution"]); // output: Flat Panel 1600 x 1200
Использование конструктора Array для создания ассоциативного массива не дает никаких особых преимуществ. С ассоциативными массивами нельзя использовать свойство Array.length
или любой из методов класса Array, даже если вы используете конструктор Array или тип данных Array. Конструктор Array лучше всего подходит для создания индексных массивов.
Ассоциативные массивы с объектами-ключами (Словари)
Можно использовать класс Dictionary для создания ассоциативного массива, использующего в качестве ключей объекты, а не строки. Такие массивы иногда называют словарями, хеш-таблицами или преобразованиями. Например, рассмотрим приложение, определяющее расположение объекта Sprite на основании его связи с определенным контейнером. Можно использовать объект Dictionary, чтобы сопоставить каждый объект Sprite с контейнером.
В примере ниже создаются три экземпляра класса Sprite, которые служат ключами для объекта Dictionary. Каждому ключу задается значение GroupA
или GroupB
. Значения могут быть любого типа данных, но в этом примере и GroupA
, и GroupB
являются экземплярами класса Object. Следовательно, доступ к значениям, связанным с каждым из ключей с оператором доступа к массиву (
[]
), осуществляется как показано ниже:
182
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
import flash.display.Sprite; import flash.utils.Dictionary; var groupMap:Dictionary = new Dictionary(); // objects to use as keys var spr1:Sprite = new Sprite(); var spr2:Sprite = new Sprite(); var spr3:Sprite = new Sprite(); // objects to use as values var groupA:Object = new Object(); var groupB:Object = new Object(); // Create new key-value pairs in dictionary. groupMap[spr1] = groupA; groupMap[spr2] = groupB; groupMap[spr3] = groupB; if (groupMap[spr1] == groupA) { trace("spr1 is in groupA"); } if (groupMap[spr2] == groupB) { trace("spr2 is in groupB"); } if (groupMap[spr3] == groupB) { trace("spr3 is in groupB"); }
Итерации с объектами-ключами
Можно выполнять итерацию в объекте Dictionary с помощью цикла for..in
или for each..in
. Цикл for..in
позволяет выполнять итерацию на основе ключей, а цикл for each..in
— на основе значений, связанных с ключами.
Используйте цикл for..in
для прямого доступа к объектам-ключам объекта Dictionary. Доступ к значениям объекта Dictionary возможен и без оператора доступа к массиву (
[]
). В приведенном ниже коде словарь groupMap
из предыдущего примера используется для выполнения итерации в объекте Dictionary с помощью цикла for..in
:
for (var key:Object in groupMap) { trace(key, groupMap[key]); } /* output: [object Sprite] [object Object] [object Sprite] [object Object] [object Sprite] [object Object] */
Используйте цикл for each..in
для прямого доступа к значениям объекта Dictionary. В приведенном ниже коде словарь groupMap
используется для выполнения итерации в объекте Dictionary с помощью цикла for each..in
:
183
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
for each (var item:Object in groupMap) { trace(item); } /* output: [object Object] [object Object] [object Object] */
Объекты-ключи и управление памятью
Проигрыватель Adobe® Flash® и среда Adobe® AIR™ используют систему сборки мусора для восстановления памяти, которая больше не используется. Когда на объект не ведет ни одна ссылка, он становится кандидатом на сборку в мусор, поэтому при следующей сборке мусора занимаемая им память высвобождается. Например, в приведенном ниже коде создается новый объект, а переменной myObject
назначается ссылка на объект:
var myObject:Object = new Object();
Покуда на объект указывает хотя бы одна ссылка, сборщик мусора не будет высвобождать занимаемую им память. Если значение myObject
меняется и теперь указывает на другой объект или становится null
, то память, занимаемая исходным объектом, подлежит сборке в мусор, но лишь в том случае, если на исходный объект не ведут другие ссылки. Если myObject
используется как ключ в объекте Dictionary, создается еще одна ссылка на исходный объект. Например, в приведенном ниже коде, создаются две ссылки на объект: переменную myObject
и ключ в объекте myMap
:
import flash.utils.Dictionary; var myObject:Object = new Object(); var myMap:Dictionary = new Dictionary(); myMap[myObject] = "foo";
Чтобы объект, на который ссылается myObject
, мог быть собран в мусор, необходимо удалить все ссылки на него. В этом случае нужно изменить значение myObject
и удалить ключ myObject
из myMap
, как показано ниже:
myObject = null; delete myMap[myObject];
Вы также можете использовать параметр useWeakReference
конструктора Dictionary, чтобы превратить все ключи словаря в слабые ссылки. Сборщик мусора игнорирует слабые ссылки, т.е. объект, на который ведут только слабые ссылки, подлежит сборке в мусор. Например, в приведенном ниже коде не нужно удалять ключ myObject
из myMap
, чтобы объект можно было собрать в мусор:
import flash.utils.Dictionary; var myObject:Object = new Object(); var myMap:Dictionary = new Dictionary(true); myMap[myObject] = "foo"; myObject = null; // Make object eligible for garbage collection.
Многомерные массивы
Элементами многомерных массивов являются другие массивы. Например, рассмотрим план на неделю, сохраненный в виде индексного массива строк:
184
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
var tasks:Array = ["wash dishes", "take out trash"];
Если нужно сохранить отдельный список дел для каждого дня недели, вы можете создать многомерный массив, где каждый день недели будет элементом. Каждый элемент содержит индексный массив, похожий на массив tasks
, в котором хранится список задач. В многомерных массивах можно использовать любую комбинацию ассоциативных массивов. В примерах из следующих разделов используются два индексных массива или ассоциативный массив индексных массивов. Вы можете попробовать другие сочетания. Два индексных массива
При использовании двух индексных массивов можно визуально представить результат как таблицу. Элементы первого массива будут строками таблицы, а элементы второго — столбцами. Например, в следующем многомерном массиве два индексных массива используются для отслеживания списков дел для каждого дня недели. Первый массив, masterTaskList
, создается с помощью конструктора класса Array. Каждый элемент массива представляет один из дней недели, где 0 — это понедельник, а 6 — воскресенье. Эти элементы будут рядами таблицы. Задача для каждого дня создается путем назначения литерала массива каждому из семи элементов, созданных в массиве masterTaskList
. Литералы массива представляют столбцы таблицы.
var masterTaskList:Array = new Array(); masterTaskList[0] = ["wash dishes", "take out trash"]; masterTaskList[1] = ["wash dishes", "pay bills"]; masterTaskList[2] = ["wash dishes", "dentist", "wash dog"]; masterTaskList[3] = ["wash dishes"]; masterTaskList[4] = ["wash dishes", "clean house"]; masterTaskList[5] = ["wash dishes", "wash car", "pay rent"]; masterTaskList[6] = ["mow lawn", "fix chair"];
Обращаться к отдельным элементам в любых списках задач можно с помощью оператора доступа к массиву (
[]
). Первая пара квадратных скобок представляет день недели, а вторая — список дел для этого дня. Например, для получения второй задачи из списка дел на среду нужно сначала использовать индекс 2 для среды, а потом индекс 1 для второй задачи в списке.
trace(masterTaskList[2][1]); // output: dentist
Чтобы получить первую задачу из списка дел на воскресенье, используйте индекс 6 для вызова воскресенья, а затем индекс 0 для первой задачи.
trace(masterTaskList[6][0]); // output: mow lawn
Ассоциативный массив с индексным массивом
Чтобы упростить доступ к отдельным массивам, используйте ассоциативный массив для дней недели и индексный массив для списков задач. Использование ассоциативного массива позволяет использовать синтаксис записи через точку при обращении к определенному дню недели, но обращение к каждому элементу ассоциативного массива потребует дополнительного времени обработки. В примере ниже показано, как использовать для списка задач ассоциативный массив с парами «ключ-значение» для каждого из дней недели: 185
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
var masterTaskList:Object = new Object(); masterTaskList["Monday"] = ["wash dishes", "take out trash"]; masterTaskList["Tuesday"] = ["wash dishes", "pay bills"]; masterTaskList["Wednesday"] = ["wash dishes", "dentist", "wash dog"]; masterTaskList["Thursday"] = ["wash dishes"]; masterTaskList["Friday"] = ["wash dishes", "clean house"]; masterTaskList["Saturday"] = ["wash dishes", "wash car", "pay rent"]; masterTaskList["Sunday"] = ["mow lawn", "fix chair"];
Синтаксис записи через точку повышает удобочитаемость кода, избавляя его от многочисленных квадратных скобок.
trace(masterTaskList.Wednesday[1]); // output: dentist trace(masterTaskList.Sunday[0]);// output: mow lawn
Можно выполнять итерацию в списке задач с помощью цикла for..in
, но тогда вместо синтаксиса записи через точку нужно использовать оператор доступа к массиву (
[]
) для получения значений, связанных с ключами. Так как masterTaskList
является ассоциативным массивом, его элементы необязательно будут вызываться по порядку, что демонстрируется в примере ниже:
for (var day:String in masterTaskList) { trace(day + ": " + masterTaskList[day]) } /* output: Sunday: mow lawn,fix chair Wednesday: wash dishes,dentist,wash dog Friday: wash dishes,clean house Thursday: wash dishes Monday: wash dishes,take out trash Saturday: wash dishes,wash car,pay rent Tuesday: wash dishes,pay bills */
Клонирование массивов
У класса Array нет встроенного метода для создания копий массивов. Можно создать поверхностнуюкопию массива путем вызова метода concat()
или slice()
без аргументов. Если элементами исходного массива являются объекты, то поверхностная копия будет содержать только ссылки на объекты, а не сами объекты. Копия указывает на те же объекты, что и оригинал. Любые изменения объектов отражаются в обоих массивах.
В глубокой копии все объекты, обнаруженные в исходном массиве, копируются, так что новый массив не указывает на те же объекты, что исходный. При глубоком копировании требуется более одной строки кода, для чего обычно нужно создать функцию. Можно создать глобальную вспомогательную функцию или метод подкласса Array.
В примере ниже определяется функции clone()
, которая выполняет глубокое копирование. Алгоритм заимствован у широко используемой техники языка Java. Функция создает глубокую копию, упорядочивая массив и превращая его в экземпляр класса ByteArray, а затем заново считывая его в новый массив. Эта функция принимает объект, так чтобы его можно было использовать как с индексными массивами, так и с ассоциативными, как показано в коде ниже:
186
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
import flash.utils.ByteArray; function clone(source:Object):* { var myBA:ByteArray = new ByteArray(); myBA.writeObject(source); myBA.position = 0; return(myBA.readObject()); }
Дополнительные темы
Расширение класса Array
Класс Array — это один из нескольких ключевых нефинальных классов, то есть он позволяет создавать собственные подклассы класса Array. В этом разделе приводится пример того, как создавать подкласс класса Array и рассказывается о некоторых проблемах, которые могут возникнуть при выполнении этой операции. Как было сказано выше, массивы в языке ActionScript не типизированные, но можно создать подкласс класса Array, который будет принимать элементы только определенного типа данных. В примере в последующих разделах определяется подкласс класса Array с именем TypedArray, в первом параметре которого накладывается ограничение на тип данных элементов. Класс TypedArray представлен исключительно в качестве примера того, как расширить класс Array, и может не подойти для практического применения по ряду причин. Во-первых, проверка типа производится во время выполнения, а не при компиляции. Во-
вторых, когда метод TypedArray сталкивается с несовпадением, он игнорирует его, а исключение при этом не генерируется, хотя можно легко модифицировать методы, чтобы они генерировали исключения. В-третьих, класс не может предотвратить использование оператора доступа к массиву для вставки значений какого-либо типа в массив. В-четвертых, в силу стиля кода предпочтение отдается простоте, а не оптимизации.
Примечание. Описанный здесь прием можно использовать для создания типизированного массива. Однако для этого лучше использовать объект Vector. Экземпляр Vector является настоящим типизированным массивом и превосходит класс Array и его подклассы по производительности и другим показателям. В целях данного обсуждения демонстрируется создание подкласса Array.
Объявление подкласса
Используйте ключевое слово extends
для обозначения того, что класс является подклассом класса Array. Подкласс класса должен использовать атрибут dynamic
, как и класс Array. В противном случае подкласс будет работать некорректно. В приведенном ниже коде дается определение класса TypedArray, содержащего константу для хранения типа данных, метод конструктора и четыре метода для добавления элементов в массив. В этом примере не приводится код для каждого из методов, но он подробным образом освещается в последующих разделах:
187
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
public dynamic class TypedArray extends Array { private const dataType:Class; public function TypedArray(...args) {} AS3 override function concat(...args):Array {} AS3 override function push(...args):uint {} AS3 override function splice(...args) {} AS3 override function unshift(...args):uint {} }
Четыре переопределенных метода используют пространство имен AS3 вместо атрибута public
, потому что в данном примере мы исходим из того, что параметр компилятора -as3
= true
, а параметр компилятора -es
= false
. Это настройки по умолчанию для Adobe Flex Builder 3 и Adobe® Flash® CS4 Professional. Дополнительную информацию см. в разделе «Пространство имен AS3» на странице 133.
Если вы опытный разработчик и предпочитаете использовать прототипное наследование, то можете внести две небольших правки в класс TypedArray, чтобы компиляция выполнялась с помощью параметра компиляции -es
со значением true
. Во-первых, удалите все вхождения атрибута override
и замените пространство имен AS3 атрибутом public
. Во-вторых, замените все четыре вхождения super
на Array.prototypesuper
.
Конструктор TypedArray
Конструктор подкласса ставит перед разработчиком интересную задачу, так как конструктор должен принимать список аргументов любой длины. Сложность состоит в том, как передавать аргументы суперконструктору для создания массива. Если список аргументов передается как массив, суперконструктор расценивает его как единственный аргумент типа Array, и итоговый массив всегда состоит из 1 элемента. Традиционно список аргументов передается с помощью метода Function.apply()
, который принимает массив аргументов в качестве второго параметра, но преобразует его в список аргументов при выполнении функции. К сожалению, метод Function.apply()
нельзя использовать с конструкторами.
Единственный оставшийся вариант — воссоздать логику конструктора Array в конструкторе TypedArray. В приведенном ниже коде показан алгоритм, используемый в конструкторе класса Array, который можно использовать и в конструкторе подкласса Array:
188
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
public dynamic class Array { public function Array(...args) { var n:uint = args.length if (n == 1 && (args[0] is Number)) { var dlen:Number = args[0]; var ulen:uint = dlen; if (ulen != dlen) { throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")"); } length = ulen; } else { length = n; for (var i:int=0; i < n; i++) { this[i] = args[i] } } } }
Большая часть кода конструктора TypedArray идентична коду конструктора класса Array, за исключением четырех отличий. Во-первых, список параметров включает новый обязательный параметр типа Class, позволяющий задавать тип данных массива. Во-вторых, тип данных, передаваемых конструктору назначается переменной dataType
. В-третьих, инструкция else
— значение свойства length
— назначается после цикла for
, поэтому length
включает только аргументы правильного типа. В-четвертых, внутри цикла for
используется переопределенный вариант метода push()
, поэтому к массиву добавляются только аргументы правильного типа данных. В примере ниже показана функция конструктора TypedArray:
189
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
public dynamic class TypedArray extends Array { private var dataType:Class; public function TypedArray(typeParam:Class, ...args) { dataType = typeParam; var n:uint = args.length if (n == 1 && (args[0] is Number)) { var dlen:Number = args[0]; var ulen:uint = dlen if (ulen != dlen) { throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")") } length = ulen; } else { for (var i:int=0; i < n; i++) { // type check done in push() this.push(args[i]) } length = this.length; } } }
Переопределенные методы TypedArray
Класс TypedArray переопределяет четыре метода класса Array, которые позволяют добавлять элементы в массив. В каждом случае переопределенный метод добавляет проверку типа, чтобы гарантировать только добавление элементов правильного типа. Следовательно, каждый метод вызывает вариант самого себя для суперкласса.
Метод push()
выполняет итерацию в списке аргументов с помощью цикла for..in
и проверку типа для каждого аргумента. Любой аргумент, не соответствующий правильному типу, удаляется из массива args
методом splice()
. После окончания цикла for..in
в массиве args
остаются только значения типа dataType
. Затем вызывается вариант метода push()
для суперкласса с обновленным массивом args
, как показано в коде ниже:
AS3 override function push(...args):uint { for (var i:* in args) { if (!(args[i] is dataType)) { args.splice(i,1); } } return (super.push.apply(this, args)); }
190
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Метод concat()
создает временный TypedArray с именем passArgs
для хранения аргументов, передающих проверку типа. Это позволяет повторно использовать процедуру проверки типа метода push()
. Цикл for..in
выполняет итерацию в массиве args
и вызывает метод push()
для каждого аргумента. Так как типом passArgs
является TypedArray, выполняется метод push()
для TypedArray. Метод concat()
далее вызывает собственный вариант для суперкласса, как показано ниже:
AS3 override function concat(...args):Array { var passArgs:TypedArray = new TypedArray(dataType); for (var i:* in args) { // type check done in push() passArgs.push(args[i]); } return (super.concat.apply(this, passArgs)); }
Метод splice()
принимает произвольный список аргументов, но первые два аргумента всегда обозначают индекс и число удаляемых элементов. Именно поэтому переопределенный метод splice()
выполняет проверку типа только для элементов массива args
с индексами 2 и более. Отдельного внимания заслуживает то, что в коде рекурсивно вызывается метод splice()
внутри цикла for
, но это не рекурсивный вызов, потому что args
относится к типу Array, а не TypedArray, следовательно, вызов args.splice()
является вызовом варианта метода для суперкласса. После окончания цикла for..in
завершается, в массиве args
остаются значения правильного типа с индексами 2 и выше, а метод splice()
вызывает свою версию для суперкласса, как показано ниже:
AS3 override function splice(...args):* { if (args.length > 2) { for (var i:int=2; i< args.length; i++) { if (!(args[i] is dataType)) { args.splice(i,1); } } } return (super.splice.apply(this, args)); }
Метод unshift()
, добавляющий элементы в начало массива, также принимает произвольный список аргументов. Переопределенный метод unshift()
использует алгоритм, очень похожий на метод push()
, как показано в приведенном ниже коде:
AS3 override function unshift(...args):uint { for (var i:* in args) { if (!(args[i] is dataType)) { args.splice(i,1); } } return (super.unshift.apply(this, args)); } }
191
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Пример: PlayList
В примере PlayList показаны техники работы с массивами в контексте приложения, управляющего списками воспроизведения песен. Рассматриваются следующие техники:
•
создание индексного массива;
•
добавление элементов в индексный массив;
•
сортировка массива объектов по различным свойствам с помощью нескольких параметров сортировки;
•
преобразование массива в строку значений, разделенных заданным символом.
Файлы приложений для этого примера можно найти по адресу: www.adobe.com/go/learn_programmingAS3samples_flash_ru. Файлы приложения PlayList находятся в каталоге Samples/PlayList. Приложение состоит из следующих файлов.
Обзор класса PlayList
Класс PlayList управляет набором объектов Song. У него есть публичные методы с функциональностью, поддерживающей добавление песен в список воспроизведения (метод addSong()
) и их сортировку в списке (метод sortList()
). Кроме того, класс включает свойство доступа только для чтения, songList
, позволяющее подключаться к действительному списку песен в списке воспроизведения. Внутри класса PlayList песни отслеживаются с помощью частной переменной Array:
public class PlayList { private var _songs:Array; private var _currentSort:SortProperty = null; private var _needToSort:Boolean = false; ... }
Кроме переменной класса Array _songs
, которая используется классом PlayList для отслеживания списка песен, две другие частные переменные отслеживают, нужно ли сортировать список (
_needToSort
) и какое свойство нужно использовать для сортировки в заданное время (
_currentSort
).
Как и в случае всех остальных объектов, объявление экземпляра Array — это лишь половина успеха в деле создания массива. Прежде чем пользоваться свойствами или методами экземпляра Array, необходимо создать экземпляр с помощью конструктора класса PlayList.
Файл Описание
PlayList.mxml
или
PlayList.fla
Основной файл приложения Flash (FLA) или Flex (MXML).
com/example/programmingas3/playlist/PlayList.as Класс, отвечающий за отображение списка композиций. Для хранения списка данный класс использует Array. Он также отвечает за сортировку элементов списка.
com/example/programmingas3/playlist/Song.as Объект значения, представляющий информацию об отдельной песне. Элементы, управляемые классом PlayList, являются экземплярами Song.
com/example/programmingas3/playlist/SortProperty.as Псевдоперечисление, доступные значения которого представляют свойства класса Song, по которым сортируются объекты Song в списке.
192
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
public function PlayList() { this._songs = new Array(); // Set the initial sorting. this.sortList(SortProperty.TITLE); }
Первая строка конструктора создает экземпляр переменной _songs
, которая готова к использованию. Кроме того, для установки начального свойства сортировки вызывается метод sortList()
.
Добавление песни в список
Когда пользователь добавляет в приложение новую песню, код в элементе данных вызывает метод класса PlayList addSong()
.
/** * Adds a song to the playlist. */ public function addSong(song:Song):void { this._songs.push(song); this._needToSort = true; }
Внутри метода addSong()
вызывается метод push()
массива _songs
, который добавляет объект Song, переданный методу addSong()
, в качестве нового элемента массива. Метод push()
добавляет новый элемент в конец массива, независимо от того, выполнялась ли ранее сортировка массива. Это означает, что после вызова метода push()
список песен вряд ли будет отсортирован правильно, поэтому нужно задать переменной _needToSort
значение true
. В теории метод sortList()
можно вызвать незамедлительно, благодаря чему не нужно будет отслеживать, отсортирован ли список в тот или иной момент времени. Однако на практике список песен нужно сортировать лишь непосредственно перед тем, как к нему обратятся. Отказываясь от сортировки, приложение пропускает ненужные операции, например, в случае, если к списку до обращения было добавлено несколько песен.
Сортировка списка песен
Так как экземпляры Song, которыми управляет список воспроизведения, являются сложными объектами, пользователям приложения может потребоваться выполнить сортировку списка песен по разным свойствам, например по названию или по году выпуска. В приложении PlayList задача сортировки списка песен состоит из трех частей: определение свойства, по которому выполняется сортировка; определение параметров сортировки при сортировке по этому свойству; выполнение собственно операции сортировки.
Свойства сортировки
Объект Song отслеживает некоторые свойства, включая название песни, имя исполнителя, год выпуска, имя файла и жанр песни, который выбирает сам пользователь. Для сортировки подходят только первые три. Для удобства разработчиков в пример включен класс SortProperty, действующий как перечисление со значениями, представляющими свойства для сортировки.
public static const TITLE:SortProperty = new SortProperty("title"); public static const ARTIST:SortProperty = new SortProperty("artist"); public static const YEAR:SortProperty = new SortProperty("year");
193
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Класс SortProperty содержит три переменные: TITLE
, ARTIST
и YEAR
, в каждой из которых хранится строка с именем связанного свойства класса Song, используемого при сортировке. В остальном коде свойство сортировки определяется с помощью члена перечисления. Например, в конструкторе PlayList список изначально сортируется путем вызова метода sortList()
, как показано ниже:
// Set the initial sorting. this.sortList(SortProperty.TITLE);
Свойство сортировки задано в форме SortProperty.TITLE
, поэтому песни сортируются по названию.
Сортировка по свойству и установка свойств сортировки
Сама сортировка выполняется классом PlayList в методе sortList()
, как показано ниже:
/** * Sorts the list of songs according to the specified property. */ public function sortList(sortProperty:SortProperty):void { ... var sortOptions:uint; switch (sortProperty) { case SortProperty.TITLE: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.ARTIST: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.YEAR: sortOptions = Array.NUMERIC; break; } // Perform the actual sorting of the data. this._songs.sortOn(sortProperty.propertyName, sortOptions); // Save the current sort property. this._currentSort = sortProperty; // Record that the list is sorted. this._needToSort = false; }
При сортировке по названию или имени исполнителя имеет смысл следовать алфавитному порядку, но при сортировке по году выпуска разумнее использовать числовой порядок. Инструкция switch
используется для определения подходящего параметра сортировки, хранящегося в переменной sortOptions
, о чем говорит значение, заданное в параметре sortProperty
. Здесь члены перечисления снова используются для различения свойств, а не жестко заданных значений.
Когда параметры и свойства сортировки определены, массив _songs
сортируется путем вызова метода sortOn()
, который передает эти два значения в качестве параметров. Записывается текущее свойство сортировки, а также фиксируется сам факт сортировки.
194
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Работа с массивами
Объединение элементов массива в строку значений, разделенных символом
Массив в данном примере используется не только для хранения списка песен в классе PlayList, но и для управления списком жанров песен в классе Song. Обратите внимание на следующий фрагмент кода из определения класса Song:
private var _genres:String; public function Song(title:String, artist:String, year:uint, filename:String, genres:Array) { ... // Genres are passed in as an array // but stored as a semicolon-separated string. this._genres = genres.join(";"); }
При создании нового экземпляра Song, параметр genres
, используемый для указания жанра (или жанров) песни, определяется как экземпляр Array. Это упрощает группировку нескольких жанров в единую переменную, которую затем можно передавать конструктору. Тем не менее, внутри класса Song жанры хранятся в частной переменной _genres
в виде экземпляра String со значениями, разделенными точкой с запятой. Параметр Array преобразуется в строку значений, разделенных точкой с запятой, путем вызова метода join()
со значением литерала строки ";"
в качестве разделителя.
По такому же принципу методы доступа genres
поддерживают установку или извлечение жанров в виде массива:
public function get genres():Array { // Genres are stored as a semicolon-separated String, // so they need to be transformed into an Array to pass them back out. return this._genres.split(";"); } public function set genres(value:Array):void { // Genres are passed in as an array, // but stored as a semicolon-separated string. this._genres = value.join(";"); }
Метод доступа genresset
работает как конструктор: он принимает массив и вызывает метод join()
для преобразования массива в строку значений, разделенных точкой с запятой. Метод доступа get
выполняет обратную операцию: вызывается метод split()
переменой _genres
, и строка разбивается на массив значений с помощью заданного разделителя (литералом строки, как и прежде, является символ ";"
).
195
Глава 9. Обработка ошибок
Система обработки ошибок базируется на встроенной в приложение логике, которая отвечает на ошибки, возникающие при составлении и выполнении программы, или автоматически устраняет их. Когда приложение обрабатывает ошибки, при их обнаружении каждый раз происходит некое событие, которое является ответом на ошибку. В противоположность этому, при отсутствии обработки ответ не возникает и, какой бы процесс за этим ни следовал, ошибка остается незамеченной. При корректном использовании система обработки ошибок помогает защитить приложение пользователя от непредсказуемого поведения.
В целом, обработка ошибок представляет собой многоплановую систему действий, включающую реакцию на многие виды ошибок, которые возникают как при составлении приложения, так и при его выполнении. Основное внимание в этой главе отводится обработке ошибок выполнения, обзору различных типов ошибок, которые могут возникнуть, и преимуществам новой системы обработки ошибок в ActionScript 3.0. Здесь говорится также о том, как вставить собственную стратегию обработки ошибок в создаваемое приложение.
Основы обработки ошибок
Введение в обработку ошибок
Ошибкой выполнения называется сбой кода ActionScript, приводящий к остановке потока содержимого в Adobe® Flash® Player или Adobe® AIR™. Для обеспечения безотказной работы кода ActionScript необходимо составлять такие приложения, которые обрабатывают ошибки, то есть анализируют и устраняют их или, по крайней мере, сообщают пользователю о том, что случилось. Этот процесс называется обработкой ошибок.
Обработка ошибок представляет собой многоплановую систему действий, включающую реакцию на многие виды ошибок, которые возникают как при составлении приложения, так и при его выполнении. Ошибки, возникающие во время составления программы, как правило, легче идентифицировать — их обязательно нужно устранить, чтобы завершить процесс создания SWF-файла. В этой главе ошибки составления не рассматриваются. Информацию о том, как избежать ошибок при написании кода, см. в разделах: «Язык ActionScript и его синтаксис» на странице 41 и «Объектно-ориентированное программирование на языке ActionScript» на странице 99. Эта глава посвящена обработке ошибок выполнения.
Ошибки выполнения обнаружить сложнее, поскольку для их возникновения необходимо, чтобы ошибочный код фактически был запущен. Если сегмент программы имеет несколько ветвей кода, например инструкцию if..then..else
, тогда для подтверждения отсутствия ошибок в коде необходимо проверить все возможные условия со всеми возможными реальными значениями, которые может применить будущий пользователь программы.
Ошибки выполнения можно разделить на две категории: ошибки программирования — ошибки в коде ActionScript, такие как задание неверного типа данных для параметра метода; и логические ошибки — ошибки проверки данных и ошибки управления значениями, такие как использование неверной формулы для расчета процентов в банковском приложении. Ошибки обоих этих типов часто можно обнаружить и исправить заблаговременно, если аккуратно проверить приложение.
196
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
В идеале следует найти и устранить все ошибки в создаваемом приложении, прежде чем оно поступит в распоряжение конечного пользователя. Тем не менее, не все ошибки можно предвидеть и предотвратить. Например, если приложение ActionScript загружает какую-либо информацию с веб-сайта, этот процесс выходит за пределы контроля программиста. Если какой либо ресурс веб-сайта оказывается недоступен, тогда блок программы, зависящий от внешних данных, не сможет работать корректно. Наиболее важным аспектом обработки ошибок является подготовка к таким случаям, чтобы решить проблему и обеспечить продолжение работы приложения или, по крайней мере, предусмотреть сообщение для пользователя, в котором вежливо будет объяснено, почему программа не работает.
Ошибки выполнения в ActionScript представляются двумя способами.
•
Классы ошибок: многие ошибки можно отнести к определенному классу. Когда возникает ошибка, проигрыватель Flash Player или Adobe AIR создает экземпляр специального класса ошибок, который связан с данной конкретной ошибкой. Код программы может использовать информацию, содержащуюся в объекте ошибки, чтобы подготовить соответствующий ответ на эту ошибку.
•
События ошибок: иногда ошибка возникает, когда Flash Player или Adobe AIR пытаются запустить событие. В этих случаях Flash Player или Adobe AIR запускают вместо этого событие ошибки. Как и все другие события, событие ошибки имеет свой класс. Проигрыватель Flash Player и Adobe AIR передают экземпляр этого класса методам, которые приписаны к событию ошибки.
Для определения того, может ли определенный метод генерировать ошибку или событие ошибки, см. раздел, посвященный введению методов в справочнике по языку ActionScript 3.0 и компонентам.
Общие задачи обработки ошибок
Ниже представлены общие задачи по обработке ошибок, которые обычно выполняются при составлении кода.
•
Написание кода для обработки ошибок
•
Обнаружение, перехват и повторная генерация ошибок
•
Определение пользовательского класса ошибок
•
Ответы на события ошибок и ошибки состояния
Важные понятия и термины
Ниже приводится список важных терминов, с которыми вы столкнетесь в этой главе.
•
Асинхронность: ситуация, при которой команда программы (например, вызов метода) не приводит к непосредственному результату. Результат (или ошибка) в этом случае принимает форму события.
•
Перехват: когда имеет место исключительная ситуация (ошибка выполнения) и когда код «знает» об этом, говорят, что код перехватил исключение. После того как исключение перехвачено, Flash Player или Adobe AIR прекращают информировать остальную часть программы ActionScript об этом исключении.
•
Отладочная версия: специальная версия Flash Player или Adobe AIR (ADL), содержащая код для уведомления пользователей об ошибках выполнения. В стандартных версиях Flash Player и Adobe AIR (которые использует большинство пользователей) ошибки, не обрабатываемые с помощью кода ActionScript, игнорируются. В отладочных версиях (включенных в Adobe Flash CS4 Professional и Adobe Flex) при обнаружении необработанной ошибки появляется предупреждающее сообщение.
•
Исключение: ошибка выполнения программы, которую невозможно устранить в среде выполнения, то есть в Flash Player или Adobe AIR.
197
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
•
Повторная генерация: после того как исключение перехвачено кодом, Flash Player или Adobe AIR прекращают извещать другие объекты об этом исключении. Для извещения остальных объектов об исключении важно, чтобы код мог повторно сгенерировать исключение и возобновлять процесс уведомления.
•
Синхронность: ситуация, при которой команда программы, например вызов метода, приводит к непосредственному результату или к немедленной генерации ошибки. При этом ответ может использоваться в одном и том же блоке кода.
•
Генерация: акт извещения Flash Player или Adobe AIR (и, как следствие, извещение других объектов и кода ActionScript) о возникновении ошибки называется генерацией ошибки.
Работа с примерами из главы
Прорабатывая главу, вы можете самостоятельно тестировать приведенные в ней примеры кодов. Важно, что все примеры кода в этой главе включают вызов соответствующей функции trace()
. Для тестирования кодов, приведенных в этой главе, выполните следующие действия.
1
Создайте пустой документ Flash.
2
Выберите ключевой кадр на временной шкале.
3
Откройте панель «Действия» и скопируйте код на панель «Сценарий».
4
Запустите программу, выбрав «Управление» > «Тестировать ролик».
Результаты действий функций trace()
для примеров кода можно увидеть на панели «Вывод».
Некоторые из последних кодов более сложные и написаны в виде класса. Чтобы проверить эти примеры, выполните следующие действия.
1
Создайте пустой документ Flash и сохраните его на своем компьютере.
2
Создайте новый файл ActionScript и сохраните его в том же каталоге, что и документ Flash. Имя файла должно соответствовать имени класса в тестируемом коде. Например, если в примере кода задан класс с именем ErrorTest, файл ActionScript необходимо сохранить под именем ErrorTest.as. 3
Скопируйте код в файл ActionScript и сохраните его.
4
В документе Flash щелкните пустую часть рабочей области или рабочего пространства, чтобы активировать инспектор свойств.
5
В поле «Класс документа» инспектора свойств введите имя класса ActionScript, скопированного из текста.
6
Запустите программу, выбрав «Управление» > «Тестировать ролик»
Результаты выполнения примера появятся на панели «Вывод» (если в примерах используется функция trace()
), или в текстовом поле, созданном с помощью кода примера.
Техника тестирования примеров кода описана более детально в разделе «Тестирование примеров кода» на странице 38.
198
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Типы ошибок
При создании и запуске приложений программист может столкнуться с различными типами ошибок и проблемами, связанными с терминологией обработки ошибок. Ниже приводится список основных типов ошибок и соответствующих терминов.
•
Ошибки компиляции выявляются компилятором ActionScript во время составления кода. Ошибки компиляции возникают в том случае, когда проблемы в синтаксисе кода препятствуют созданию приложения. •
Ошибки выполнения возникают после запуска скомпилированного приложения. Ошибки выполнения выявляются во время воспроизведения SWF-файла в проигрывателе Flash Player или в Adobe AIR. В большинстве случаев у программиста существуют возможности для обработки ошибок выполнения по мере их возникновения, для сообщения о них пользователю и для поддержания работоспособности приложения. Если происходит фатальная ошибка, такая как отсутствие подключения к удаленному веб-
сайту или невозможность загрузки требуемых данных, систему обработки ошибок можно использовать для корректного закрытия приложения. •
Синхронные ошибки возникают при выполнении программы во время вызова функции, например при попытке использовать определенный метод, аргумент которого оказывается недействительным. Эти ошибки приводят к генерации исключения проигрывателем Flash Player или Adobe AIR. Большинство ошибок возникает синхронно, то есть в момент выполнения инструкции. При этом процесс управления немедленно переходит к наиболее приемлемой в данном случае инструкции catch
. Например, следующий фрагмент кода генерирует ошибку выполнения, потому что метод browse()
не был вызван перед тем, как программа попыталась загрузить файл:
var fileRef:FileReference = new FileReference(); try { fileRef.upload("http://www.yourdomain.com/fileupload.cfm"); } catch (error:IllegalOperationError) { trace(error); // Error #2037: Functions called in incorrect sequence, or earlier // call was unsuccessful. }
В этом случае ошибка выполнения генерируется синхронно, поскольку Flash Player установил, что метод browse()
не был вызван перед тем, как программа попыталась загрузить файл: Для получения подробной информации по этому вопросу см. раздел «Обработка синхронных ошибок в приложении» на странице 202.
•
Асинхронныеошибки возникают на различных этапах выполнения программы. Они генерируют события и перехватываются прослушивателями событий. Асинхронные операции характеризуются тем, что функция инициирует данную операцию, но не ожидает ее завершения. Программист может создать прослушивателя события, который будет следить за операциями приложения или пользователя. Если при выполнении какой-либо операции произойдет сбой, тогда с помощью прослушивателя событий можно будет перехватить ошибку и ответить на событие ошибки. Затем прослушиватель событий вызывает функцию обработчика событий, чтобы ответить на событие ошибки наиболее эффективным образом. Например, обработчик событий может открыть диалоговое окно, чтобы помочь пользователю устранить ошибку.
199
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Рассмотрите синхронную ошибку загрузки файла в примере, который был приведен выше. В случае успешного вызова метода browse()
перед загрузкой файла Flash Player отправит несколько событий. Например, когда начнется загрузка, будет отправлено событие open
. После успешного завершения операции загрузки файла отправляется событие complete
. Поскольку обработка события выполняется асинхронно (то есть она не происходит в заданное, известное или предсказуемое время), для отслеживания этих специфических событий необходимо использовать метод addEventListener()
, как показано в следующем коде:
var fileRef:FileReference = new FileReference(); fileRef.addEventListener(Event.SELECT, selectHandler); fileRef.addEventListener(Event.OPEN, openHandler); fileRef.addEventListener(Event.COMPLETE, completeHandler); fileRef.browse(); function selectHandler(event:Event):void { trace("...select..."); var request:URLRequest = new URLRequest("http://www.yourdomain.com/fileupload.cfm"); request.method = URLRequestMethod.POST; event.target.upload(request.url); } function openHandler(event:Event):void { trace("...open..."); } function completeHandler(event:Event):void { trace("...complete..."); }
Для получения подробной информации об обработке асинхронных ошибок см. раздел «Ответы на события ошибок и ошибки состояния» на странице 207.
•
Необработанные исключения представляют собой ошибки, генерирующиеся при отсутствии соответствующей логики, которая могла бы ответить на них (например, инструкция catch
). Если приложение генерирует ошибку, когда на текущем или более высоком уровне невозможно найти соответствующую инструкцию catch
или обработчик событий для ответа на нее, тогда такая ошибка рассматривается как необработанное исключение. В процессе работы проигрыватель Flash Player преднамеренно игнорирует необработанные ошибки и пытается продолжить воспроизведение (если ошибка не приводит к закрытию текущего SWF-файла), поскольку пользователь, как правило, не может устранить такие ошибки самостоятельно. Процесс игнорирования необработанной ошибки, который называется «тихим» или скрытым сбоем, может усложнить работу отладочных приложений. Отладочная версия Flash Player в качестве ответа на необработанную ошибку останавливает текущий сценарий и отображает эту ошибку в выходных данных инструкции trace
или записывает сообщение об ошибке в журнал событий. Если объектом исключения является экземпляр класса ошибки Error (или одного из его подклассов), тогда вызывается метод getStackTrace()
, а информация трассировки стека также отображается в выходных данных инструкции trace или в журнале событий. Дополнительная информация об использовании отладочной версии Flash Player приведена в разделе «Работа с версиями Flash Player и AIR, имеющими встроенные программы отладки» на странице 201.
200
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Обработка ошибок в ActionScript 3.0
Поскольку многие приложения могут работать без создания логики обработки ошибок, некоторые разработчики не спешат встраивать средства обработки ошибок в свои программы. Тем не менее, без обработки ошибок приложение легко может «зависнуть» или разочаровать пользователя, если что-либо начнет работать не так, как ожидалось. ActionScript 2.0 имеет класс Error, позволяющий встроить логику в пользовательские функции для генерации исключения со специальным сообщением. Поскольку обработка ошибок является критическим условием для создания удобного для пользователя приложения, ActionScript 3.0 включает в себя расширенную архитектуру перехвата ошибок.
Примечание. В справочнике по языку ActionScript 3.0 и компонентам приведены исключения, генерируемые многими методами, однако он не может вместить все возможные исключения для каждого метода. Метод может генерировать исключения, связанные с ошибками синтаксиса или с другими проблемами, которые не указаны явно в описании метода, даже если в этом описании приводится список исключений, генерируемых методом.
Элементы обработки ошибок в ActionScript 3.0
В ActionScript 3.0 используются многочисленные инструменты обработки ошибок, перечисленные ниже.
•
Классы Error. ActionScript 3.0 включает большой выбор классов Error, расширяющих спектр ситуаций, которые могут создавать объекты ошибок. Каждый класс Error помогает приложению обрабатывать специфические состояния ошибки. Эти состояния могут относится к ошибкам системы (например, состояние MemoryError), к ошибкам кода (например, состояние ArgumentError), к ошибкам сети и коммуникации (например, состояние URIError) или к другим ошибкам. Для получения дополнительной информации по каждому классу см. раздел «Сравнение классов ошибок» на странице 211.
•
Уменьшение количества скрытых сбоев. В ранних версиях Flash Player ошибки генерировались и сообщались только в том случае, когда явно использовалась инструкция throw
. В проигрывателе Flash Player 9 или более поздних версиях и Adobe AIR собственные методы и свойства ActionScript генерируют ошибки выполнения, которые позволяют программисту более эффективно обрабатывать исключения в момент их возникновения, а затем индивидуально реагировать на каждое исключение. •
В процессе отладки появляются точные сообщения об ошибках. В отладочных версиях Flash Player и Adobe AIR проблемные коды и ситуации генерируют обстоятельные сообщения об ошибках, которые дают возможность легко определить причины сбоя в конкретном блоке кода. Это делает процесс устранения ошибок более эффективным. Дополнительные сведения см. в разделе «Работа с версиями Flash Player и AIR, имеющими встроенные программы отладки» на странице 201.
•
Четкое определение ошибок позволяет передать пользователям точные сообщения об ошибках во время выполнения программы. В ранних версиях Flash Player метод FileReference.upload()
возвращал логическое значение false
, если вызов метода upload()
был неуспешным, указывая при этом одну из пяти возможных ошибок. Если ошибка происходит при вызове метода upload()
в ActionScript 3.0, возможно генерировать одну из четырех специфических ошибок, что позволяет отображать более точные сообщения об ошибках для конечного пользователя.
201
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
•
Точная обработка ошибок. Для многих стандартных ситуаций генерируются четко определенные ошибки. Например, в ActionScript 2.0 перед заполнением объекта FileReference свойство name
имеет значение null
(таким образом, перед использованием или отображением свойства name
необходимо удостовериться, что это значение не установлено как null
). В ActionScript 3.0 при попытке доступа к свойству name
перед тем, как оно было заполнено, Flash Player или AIR генерирует сообщение IllegalOperationError, которое информирует о том, что значение не было задано, так что для обработки ошибки можно использовать блоки try..catch..finally
. Дополнительные сведения см. в разделе «Использование инструкций try..catch..finally» на странице 202.
•
Отсутствие существенного снижения производительности. Использование для обработки ошибок блоков try..catch..finally
требует значительно меньше дополнительных ресурсов по сравнению с предыдущими версиями ActionScript.
•
Класс ErrorEvent позволяет создавать прослушивателей для специфических событий асинхронных ошибок. Для получения подробной информации см. раздел «Ответы на события ошибок и ошибки состояния» на странице 207.
Стратегия обработки ошибок
Если приложение не сталкивается с проблемными ситуациями, оно может успешно работать даже без встроенной в его код логики обработки ошибок. Тем не менее, при возникновении сбоев в приложении, которое не имеет активной системы обработки ошибок, конечные пользователи никогда не узнают причины этих сбоев.
Существует несколько подходов к вопросу обработки ошибок в приложении. Ниже перечислены три основных способа обработки ошибок.
•
Использование инструкций try..catch..finally
. Они позволяют перехватывать синхронные ошибки при их возникновении. Инструкции можно расположить в иерархическом порядке, чтобы перехватывать исключения на различных уровнях выполнения кода. Дополнительные сведения см. в разделе «Использование инструкций try..catch..finally» на странице 202.
•
Создание пользовательских объектов ошибок. Для контроля специфических операций приложения, не предусмотренных встроенными типами ошибок, можно использовать класс Error с целью создания собственных объектов ошибок. После этого можно будет использовать инструкции try..catch..finally
совместно с созданными объектами ошибок. Для получения дополнительной информации см. раздел «Создание пользовательских классов ошибок» на странице 206.
•
Создание прослушивателей событий и обработчиков для ответа на события ошибок. Используя эту стратегию, можно создавать глобальные обработчики ошибок, которые позволяют обрабатывать подобные события без дублирования кода в блоках try..catch..finally
. С помощью этого метода можно также с большой долей вероятности перехватывать асинхронные ошибки. Для получения подробной информации см. раздел «Ответы на события ошибок и ошибки состояния» на странице 207.
Работа с версиями Flash Player и AIR, имеющими встроенные программы отладки
Компания Adobe обеспечивает разработчиков специальными версиями Flash Player и Adobe AIR, которые имеют расширенные функции отладки. Копию отладочной версии Flash Player можно получить при установке Adobe Flash CS4 Professional или Adobe Flex Builder 3. Кроме того, можно получить отладочную версию Adobe AIR, которая называется ADL, при установке любого из этих инструментов или в составе пакета Adobe AIR SDK.
202
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Существуют существенные различия в сообщениях об ошибках между отладочными и обычными версиями Flash Player и Adobe AIR. Отладочные версии сообщают тип ошибки (Error, IOError или EOFError), номер ошибки и отображают текстовое сообщение для пользователя. Обычные версии сообщают только тип ошибки и номер ошибки. Например, рассмотрим следующий код:
try { tf.text = myByteArray.readBoolean(); } catch (error:EOFError) { tf.text = error.toString(); }
Если в отладочной версии Flash Player метод readBoolean()
генерирует ошибку EOFError, в текстовом поле tf
отображается следующее сообщение: «EOFError: Error #2030: End of file was encountered.» (Обнаружен конец файла). Тот же самый код в обычной версии Flash Player или Adobe AIR покажет следующее сообщение: «EOFError: Error #2030.» Чтобы сократить ресурсы и размеры обычных версий, текстовые строки в сообщениях об ошибках не отображаются. Используя номер ошибки, можно найти сообщение об ошибке в документации (см. справочник по языку ActionScript 3.0 и компонентам). Альтернативно можно воспроизвести ошибку, используя отладочные версии Flash Player и AIR, и просмотреть полное сообщение об ошибке. Обработка синхронных ошибок в приложении
Наиболее распространенной системой обработки ошибок является синхронная логика. При этом в код вставляются инструкции, которые перехватывают синхронные ошибки во время выполнения программы. Этот тип обработки ошибок позволяет приложению обнаруживать и устранять ошибки выполнения в случае функциональных сбоев. Логика перехвата синхронных ошибок включает инструкции try..catch..finally
, которые проверяют (try) операцию, перехватывают (catch) любые ответы на ошибку от Flash Player или Adobe AIR и в заключение (finally) выполняют какую-либо другую операцию, чтобы устранить сбой программы. Использование инструкций try..catch..finally
При работе с синхронными ошибками выполнения для их перехвата используются инструкции try..catch..finally
. Когда возникает ошибка выполнения, Flash Player или Adobe AIR генерирует исключение. Это означает, что нормальное выполнение программы приостанавливается, и создается специальный объект типа Error. Затем объект Error отправляется в первый доступный блок catch
.
Инструкция try
закрывает группу инструкций, которые потенциально могут создавать ошибки. Инструкция catch
всегда используется с инструкцией try
. Если обнаруживается ошибка в одной из инструкций блока try
, начинается выполнение инструкций catch
, которые прикреплены к данной инструкции try
. Инструкция finally
закрывает инструкции, которые будут выполняться независимо от того, обнаружена ошибка в блоке try
или нет. Если ошибки нет, инструкции внутри блока finally выполняются после завершения выполнения инструкций блока try
. Если ошибка есть, сначала выполняется соответствующая инструкция catch
, затем — инструкции блока finally
. Следующий код демонстрирует синтаксис для использования инструкций try..catch..finally
:
203
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
try { // some code that could throw an error } catch (err:Error) { // code to react to the error } finally { // Code that runs whether or not an error was thrown. This code can clean // up after the error, or take steps to keep the application running. }
Каждая инструкция catch
идентифицирует специфический класс того исключения, которое он обрабатывает. Инструкция catch
может задавать только те подклассы ошибок, которые принадлежат к классу Error. Каждая инструкция catch
проверяется по порядку. Выполняется только первая инструкция catch
, которая соответствует типу генерируемой ошибки. Другими словами, если проверяется сначала класс Error высшего уровня, а затем подкласс класса Error, тогда выбран будет только класс Error высшего уровня. Эту систему иллюстрирует следующий код:
try { throw new ArgumentError("I am an ArgumentError"); } catch (error:Error) { trace("<Error> " + error.message); } catch (error:ArgumentError) { trace("<ArgumentError> " + error.message); }
Выше приведенный код отображает следующий вывод:
<Error> I am an ArgumentError
Чтобы корректно перехватить ошибку ArgumentError, необходимо наиболее специфические типы ошибок перечислить в начале, а наиболее общие — в конце, как показано в следующем примере:
try { throw new ArgumentError("I am an ArgumentError"); } catch (error:ArgumentError) { trace("<ArgumentError> " + error.message); } catch (error:Error) { trace("<Error> " + error.message); }
Некоторые методы и свойства в программном интерфейсе Flash Player генерируют ошибки выполнения, если они сталкиваются с ошибками во время работы. Например, метод close()
в классе Sound генерирует ошибку IOError, если он (метод) не в состоянии закрыть аудиопоток, как демонстрируется в следующем коде:
204
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
var mySound:Sound = new Sound(); try { mySound.close(); } catch (error:IOError) { // Error #2029: This URLStream object does not have an open stream. }
Внимательное изучение справочника по языку ActionScript 3.0 и компонентам позволит определить, какие методы генерируют исключения — эти сведения приведены в описаниях каждого метода.
Инструкция throw
Flash Player и Adobe AIR генерируют исключения при обнаружении ошибок во время выполнения приложения. Кроме того, программист может генерировать определенные исключения самостоятельно, используя инструкцию throw
. При эксплицитной генерации ошибок компания Adobe рекомендует генерировать экземпляры класса Error или его подклассов. Ниже приведен код, в котором инструкция throw
генерирует экземпляр класса Error MyErr
, а затем вызывает функцию myFunction()
для ответа после генерации ошибки:
var MyError:Error = new Error("Encountered an error with the numUsers value", 99); var numUsers:uint = 0; try { if (numUsers == 0) { trace("numUsers equals 0"); } } catch (error:uint) { throw MyError; // Catch unsigned integer errors. } catch (error:int) { throw MyError; // Catch integer errors. } catch (error:Number) { throw MyError; // Catch number errors. } catch (error:*) { throw MyError; // Catch any other error. } finally { myFunction(); // Perform any necessary cleanup here. }
Обратите внимание, что инструкции catch
упорядочены таким образом, что типы с наиболее специфичными данными следуют первыми. Если инструкция catch
с типом данных Number следует первой, тогда ни инструкция catch
с типом данных uint, ни инструкция catch с типом данных int уже не будут выполняться.
205
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Примечание. В языке программирования Java каждая функция, генерирующая исключение, должна объявить этот факт, перечислив доступные для генерации классы в предложении throws
, прикрепленном к объявлению функции. В ActionScript не требуется заявлять исключения, которые может генерировать функция.
Отображение простых сообщений об ошибках
Одним из важнейших преимуществ новой модели исключений и событий ошибки является возможность сообщения пользователю о том, когда и почему какое-либо действие не было выполнено. Задачей программиста является написать код для отображения сообщений и предусмотреть опции для ответа.
В следующем коде показано простая инструкция try..catch
для отображения сведений об ошибке в текстовом поле:
package { import flash.display.Sprite; import flash.text.TextField; public class SimpleError extends Sprite { public var employee:XML = <EmpCode> <costCenter>1234</costCenter> <costCenter>1-234</costCenter> </EmpCode>; public function SimpleError() { try { if (employee.costCenter.length() != 1) { throw new Error("Error, employee must have exactly one cost center assigned."); } } catch (error:Error) { var errorMessage:TextField = new TextField(); errorMessage.autoSize = TextFieldAutoSize.LEFT; errorMessage.textColor = 0xFF0000; errorMessage.text = error.message; addChild(errorMessage); } } } }
Используя расширенный набор классов ошибок и встроенных ошибок компиляции, ActionScript 3.0 предоставляет больше информации о сбоях по сравнению с предыдущими версиями ActionScript. Это позволяет создавать более стабильные приложения с улучшенной системой обработки ошибок. 206
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Повторная генерация ошибок
При создании приложений существуют различные ситуации, в которых требуется повторно генерировать ошибку, если ее не удалось должным образом обработать. Например, в следующем коде показан вложенный блок try..catch
, который повторно генерирует пользовательскую ошибку ApplicationError, если вложенный блок catch
не может обработать данную ошибку:
try { try { trace("<< try >>"); throw new ArgumentError("some error which will be rethrown"); } catch (error:ApplicationError) { trace("<< catch >> " + error); trace("<< throw >>"); throw error; } catch (error:Error) { trace("<< Error >> " + error); } } catch (error:ApplicationError) { trace("<< catch >> " + error); }
Результатом предыдущего фрагмента будет следующее:
<< try >> << catch >> ApplicationError: some error which will be rethrown << throw >> << catch >> ApplicationError: some error which will be rethrown
Вложенный блок try
генерирует пользовательскую ошибку ApplicationError, которая перехватывается следующим блоком catch
. Вложенный блок catch
может попытаться обработать ошибку и, если это закончится неудачей, перебросить объект ApplicationError во включающий блок try..catch
.
Создание пользовательских классов ошибок
В ActionScript можно расширить один из стандартных классов ошибок, создав таким образом свой собственный специализированный класс. Существует несколько причин для создания собственных классов ошибок.
•
Создание класса для идентификации специфических ошибок или их групп, присущих только для данного приложения. Например, может потребоваться предпринять различные действия для ошибок, генерируемых собственным кодом программиста в добавление к тем ошибкам, которые перехвачены Flash Player или Adobe AIR. Можно создать подкласс класса Error для отслеживания новых типов данных ошибок в блоках try..catch
.
207
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
•
Создание класса для обеспечения уникальных возможностей отображения ошибок, генерируемых пользовательским приложением. Например, можно создать новый метод toString()
, который форматирует сообщения об ошибках определенным образом. Можно также задать метод lookupErrorString()
, который принимает код ошибки и извлекает из него соответствующее сообщение, базируясь на языковых предпочтениях пользователя.
Специализированный класс ошибки должен расширять основной класс Error ActionScript. Ниже приведен пример специализированного класса AppError, который является расширением класса Error:
public class AppError extends Error { public function AppError(message:String, errorID:int) { super(message, errorID); } }
Следующий пример иллюстрирует использование AppError в пользовательском проекте:
try { throw new AppError("Encountered Custom AppError", 29); } catch (error:AppError) { trace(error.errorID + ": " + error.message) }
Примечание. Если требуется заменить метод Error.toString()
в пользовательском подклассе, необходимо задать для него один параметр ...
(rest). Так определяет метод Error.toString()
языковая спецификация ECMAScript, на базе которой построен язык ActionScript 3.0, и для обеспечения обратной совместимости ActionScript 3.0 определяет его так же. Таким образом, при замене метода Error.toString()
необходимо обеспечить точное соответствие параметров. Не имеет смысла задавать параметры для метода toString()
во время выполнения программы, поскольку в этом режиме они игнорируются.
Ответы на события ошибок и ошибки состояния
Одним из наиболее значительных улучшений обработки ошибок в ActionScript 3.0 является поддержка реагирования на асинхронные ошибки при выполнении программы. (Определение асинхронных ошибок см. в разделе «Типы ошибок» на странице 198). Для ответа на события ошибок можно создавать прослушивателей событий и обработчиков событий. Многие классы отправляют события ошибок тем же способом, что и другие события. Например, экземпляр класса XMLSocket при нормальных обстоятельствах отправляет события трех типов: Event.CLOSE
, Event.CONNECT
и DataEvent.DATA
. Тем не менее, в случае возникновения проблемы класс XMLSocket может отправлять события IOErrorEvent.IOError
или SecurityErrorEvent.SECURITY_ERROR
. Дополнительные сведения о прослушивателях и обработчиках событий см. в разделе «Обработка событий» на странице 264.
208
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
События ошибок подразделяются на две категории. •
События ошибок, которые расширяют класс ErrorEvent Класс flash.events.ErrorEvent содержит свойства и методы для обработки ошибок выполнения, относящихся к сетевым и коммуникационным операциям. Классы AsyncErrorEvent, IOErrorEvent и SecurityErrorEvent расширяют класс ErrorEvent. При использовании отладочных версий Flash Player или Adobe AIR диалоговое окно информирует пользователя о всех событиях ошибок, с которыми сталкивается проигрыватель, без применения функций прослушивателя.
•
События ошибок, относящиеся к состоянию
События ошибок, относящиеся к состоянию, связаны со свойствами netStatus
и status
классов сети и коммуникаций. Если Flash Player или Adobe AIR сталкиваются с проблемой при чтении или записи данных, для свойств netStatus.info.level
или status.level
(в зависимости от класса используемого объекта) устанавливается значение "error"
. Для ответа на эту ошибку необходимо проверить, содержит ли свойство level
значение "error"
в функции обработчика событий.
Работа с событиями ошибок
Класс ErrorEvent и его подклассы содержат типы ошибок, используемые для обработки ошибок, отправляемых Flash Player или Adobe AIR, когда они пытаются считывать или записывать данные.
В следующем примере используются и инструкция try..catch
и обработчики событий ошибки для отображения всех ошибок, обнаруженных в процессе чтения локального файла. Можно добавить более сложный код обработки для предоставления опций пользователю или для автоматической обработки ошибок в местах, обозначенных комментарием «your error-handling code here» (введите код обработки ошибок).
package { import flash.display.Sprite; import flash.errors.IOError; import flash.events.IOErrorEvent; import flash.events.TextEvent; import flash.media.Sound; import flash.media.SoundChannel; import flash.net.URLRequest; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class LinkEventExample extends Sprite { private var myMP3:Sound; public function LinkEventExample() { myMP3 = new Sound(); var list:TextField = new TextField(); list.autoSize = TextFieldAutoSize.LEFT; list.multiline = true; list.htmlText = "<a href=\"event:track1.mp3\">Track 1</a><br>"; list.htmlText += "<a href=\"event:track2.mp3\">Track 2</a><br>"; addEventListener(TextEvent.LINK, linkHandler); addChild(list); } private function playMP3(mp3:String):void { 209
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
try { myMP3.load(new URLRequest(mp3)); myMP3.play(); } catch (err:Error) { trace(err.message); // your error-handling code here } myMP3.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); } private function linkHandler(linkEvent:TextEvent):void { playMP3(linkEvent.text); // your error-handling code here } private function errorHandler(errorEvent:IOErrorEvent):void { trace(errorEvent.text); // your error-handling code here } } }
Работа с событиями изменения состояния
Flash Player и Adobe AIR динамически изменяют значения свойств netStatus.info.level
или status.level
для классов, поддерживающих свойство level
. Классами, имеющими свойство netStatus.info.level
, являются: NetConnection, NetStream и SharedObject. Классами, имеющими свойство status.level
, являются: HTTPStatusEvent, Camera, Microphone и LocalConnection. Можно написать функцию обработчика для ответа на изменения значения level
и отслеживания ошибок коммуникации.
В следующем примере функция netStatusHandler()
используется для проверки значения свойства level
. Если свойство level
указывает на возникновение ошибки, код трассирует сообщение: «Video stream failed» (прерывание видеопотока).
210
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
package { import flash.display.Sprite; import flash.events.NetStatusEvent; import flash.events.SecurityErrorEvent; import flash.media.Video; import flash.net.NetConnection; import flash.net.NetStream; public class VideoExample extends Sprite { private var videoUrl:String = "Video.flv"; private var connection:NetConnection; private var stream:NetStream; public function VideoExample() { connection = new NetConnection(); connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); connection.connect(null); } private function netStatusHandler(event:NetStatusEvent):void { if (event.info.level == "error") { trace("Video stream failed") } else { connectStream(); } } private function securityErrorHandler(event:SecurityErrorEvent):void { trace("securityErrorHandler: " + event); } private function connectStream():void { var stream:NetStream = new NetStream(connection); var video:Video = new Video(); video.attachNetStream(stream); stream.play(videoUrl); addChild(video); } } }
211
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Сравнение классов ошибок
ActionScript содержит определенное количество предопределенных классов Error. Многие из этих классов используются Flash Player и Adobe AIR, но программист может использовать те же классы ошибок в своем коде. В ActionScript 3.0 есть два основных типа классов ошибок: базовые классы Error и пакет классов flash.error. Базовые классы Error установлены 3-й редакцией языковой спецификации ECMAScript (ECMA-
262). Пакет flash.error содержит дополнительные классы, введенные для облегчения процесса разработки и отладки приложений ActionScript 3.0.
Базовые классы Error ECMAScript
Базовые классы Error ECMAScript включают в себя: EvalError, RangeError, ReferenceError, SyntaxError, TypeError и URIError. Все эти классы расположены на верхних уровнях пространства имен.
Имя класса Описание Примечания
Error Класс Error используется для генерации исключений. Он является базовым классом для других классов исключений, определенных в ECMAScript: EvalError, RangeError, ReferenceError, SyntaxError, TypeError и URIError.
Класс Error является базовым для всех ошибок выполнения, генерируемых Flash
®
Player и Adobe
®
AIR
®
. Его рекомендуется использовать в качестве основы для пользовательских классов ошибок.
EvalError Исключение EvalError генерируется, если какие-
либо параметры передаются конструктору функции класса, а также если код пользователя вызывает функцию eval()
.
В ActionScript 3.0 отсутствует поддержка функции eval()
, поэтому попытка ее использования приводит к генерации ошибки.
В более ранних версиях Flash Player функция eval()
использовалась для доступа с помощью имени к переменным, свойствам, объектам или фрагментам роликов.
RangeError Исключение RangeError генерируется, если числовое значение выходит за пределы допустимого диапазона.
Например, RangeError генерируется классом Timer, если задержка имеет отрицательное или бесконечное значение. RangeError генерируется также при попытке добавить экранный объект с недопустимой глубиной.
ReferenceError Исключение ReferenceError генерируется при попытке выполнить ссылку на неопределенное свойство для защищенного (нединамического) объекта. Версии компилятора до ActionScript 3.0 не генерировали ошибку при попытке доступа к свойству undefined
. Однако в такой ситуации ActionScript 3.0 выдает исключение ReferenceError.
Исключения для не определенных переменных указывают на потенциальные ошибки и помогают повысить качество программного продукта. Однако тем программистам, которые не имеют привычки инициализировать свои переменные, придется несколько изменить свою манеру написания кода в связи с этими нововведениями в ActionScript.
212
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Базовые классы Error ActionScript
В дополнение к базовым классам ECMAScript в ActionScript добавлены различные классы для определения собственных специфических условий ошибок и расширения функциональных возможностей обработки ошибок.
Поскольку эти классы ActionScript являются расширением классов, установленных 3-й редакцией языковой спецификации ECMAScript (и фактически являются потенциальным приложением к классам будущей версии спецификации), они расположены на верхних уровнях, в отличие от классов flash.error, размещенных в отдельном пакете.
SyntaxError Исключение SyntaxError генерируется, если в коде ActionScript имеет место ошибка синтаксического разбора.
Дополнительные сведения см. в разделе 15.11.6.4 языковой спецификации ECMAScript (ECMA-262), версия 3 на веб-сайте www.ecma-
international.org/publications/standards/Ecma-
262.htm, а также раздел 10.3.1 спецификации ECMAScript для XML (E4X) (ECMA-357, версия 2) на веб-сайте www.ecma-
international.org/publications/standards/Ecma-
357.htm.
Исключение SyntaxError генерируется при нижеследующих обстоятельствах.
•
ActionScript генерирует исключения SyntaxError, когда при синтаксическом разборе классом RegExp обнаружено недействительное регулярное выражение.
•
ActionScript генерирует исключения SyntaxError, когда при синтаксическом разборе классом XMLDocument обнаружен недействительный XML.
TypeError Исключение TypeError генерируется, если фактический тип операнда отличается от ожидаемого типа.
Дополнительные сведения см. в разделе 15.11.6.5 спецификации ECMAScript на веб-сайте www.ecma-
international.org/publications/standards/Ecma-
262.htm, а также раздел 10.3 спецификации E4X www.ecma-
international.org/publications/standards/Ecma-
357.htm.
Исключение TypeError генерируется при следующих обстоятельствах:
•
Фактический параметр функции или метода не удается принудительно привязать к типу формального параметра.
•
Переменной присваивается значение, которое нельзя принудительно привязать к типу переменной.
•
Правая сторона оператора is
или instanceof
не принадлежит действительному типу.
•
Ключевое слово super
используется неправомерно.
•
При поиске свойства найдено более одной привязки, и из-за этого результаты противоречивы.
•
Метод инициирован по отношению к несовместимому объекту. Например, исключение TypeError генерируется, если метод класса RegExp «прививается» на родовой объект, а затем инициируется.
URIError Исключение URIError генерируется, если способ использования одной из глобальных функций обработки URI несовместим с ее определением.
Дополнительные сведения см. в разделе 15.11.6.6 спецификации ECMAScript на веб-сайте www.ecma-
international.org/publications/standards/Ecma-
262.htm.
Исключение URIError генерируется при следующих обстоятельствах:
Недействительный URI указан для функции программного интерфейса (API) проигрывателя Flash Player, которая ожидает URI типа Socket.connect()
.
Имя класса Описание Примечания
213
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Пакет классов ошибок flash.error
Пакет flash.error содержит классы Error, которые считаются частью интерфейса Flash Player. В отличие от вышеописанных классов, пакет flash.error связан с теми событиями ошибки, которые специфичны для Flash Player или Adobe AIR.
Имя класса Описание Примечания
ArgumentError Класс ArgumentError представляет ошибку, которая возникает, если значения параметров, переданные при вызове функции, не совпадают с параметрами, определенными для этой функции.
Ниже приведены примеры ошибок аргумента.
•
Слишком мало или слишком много аргументов передается методу.
•
Ожидается, что аргумент будет принадлежать к перечислимому типу, но он не оказывается таковым.
SecurityError Исключение SecurityError генерируется, если имеет место нарушение среды безопасности и в доступе отказано.
Ниже приведены примеры ошибок безопасности.
•
Несанкционированный доступ к свойству или вызов метода, выполненные из-за границы изолированной программной среды.
•
Предпринята попытка доступа к URL, не разрешенному изолированной программной средой.
•
Предпринята попытка подключения к сокету, но у данного порта не было необходимого файла политики. •
Предпринята попытка доступа к видеокамере или микрофону пользователя. Пользователь отклонил запрос на доступ к устройству.
VerifyError Исключение VerifyError генерируется, если обнаружен некорректный или поврежденный SWF-
файл.
Когда один SWF-файл загружает другой SWF-файл, исходный файл может перехватить исключение VerifyError, генерируемое загружаемым файлом.
214
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Имя класса Описание Примечания
EOFError Исключение EOFError генерируется при попытке чтения за пределом доступных данных.
Например, ошибка EOFError генерируется, когда вызывается один из методов чтения в интерфейсе IDataInput, а данных недостаточно для удовлетворения запроса на чтение.
IllegalOperationError Исключение IllegalOperationError генерируется, если метод не реализован или реализация не рассчитана на текущее применение.
Ниже приведены примеры ошибок для запрещенных операций.
•
Базовый класс, такой как DisplayObjectContainer, обеспечивает больше функций, чем рабочая область в состоянии поддерживать. Например, при попытке получить или задать маску в рабочей области (используя stage.mask
), Flash Player и Adobe AIR будут генерировать ошибку IllegalOperationError вместе с сообщением: «The Stage class does not implement this property or method.» (Рабочая область не поддерживает это свойство или метод). •
Подкласс наследует метод, который ему не требуется и который он может не поддерживать.
•
Определенные методы специальных возможностей вызываются, когда компиляция проигрывателя Flash Player не поддерживает специальные возможности.
•
Специальные функции вызываются в обычной версии проигрывателя Flash Player (с неполным набором функций).
•
Пользователь пытается задать имя объекта, находящегося на временная шкале.
IOError Исключение IOError генерируется при некоторых ошибках ввода-вывода.
Например, эта ошибка возникает при попытке чтения/записи на сокете, который не был подключен или был отключен.
215
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Пример: приложение CustomErrors
Приложение CustomErrors демонстрирует методы работы с пользовательскими ошибками при создании программы. Рассматриваются следующие техники:
•
Подтверждение пакета XML
•
Создание пользовательской ошибки
•
Генерация пользовательской ошибки
•
Уведомление пользователей о генерации ошибки
Для получения файлов приложения этого примера см. www.adobe.com/go/learn_programmingAS3samples_flash_ru. Файлы приложения CustomErrors находятся в папке Samples/CustomError. Приложение состоит из следующих файлов.
MemoryError Исключение MemoryError генерируется при ошибке выполнения запроса на выделение памяти.
По умолчанию виртуальная машина 2 ActionScript не накладывает ограничений на выделение памяти программой ActionScript. На персональных компьютерах отказы при выделении памяти происходят редко. Ошибка генерируется, когда система не может выделить достаточно памяти для выполнения операции. Следовательно, на персональных компьютерах это исключение возникает редко, если только не требуется чрезмерный объем памяти. Например, запрос на 3 ГБ выполнить невозможно, поскольку 32-
разрядная программа Microsoft ®
Windows
®
может получить доступ только к 2 ГБ адресного пространства.
ScriptTimeoutError Исключение ScriptTimeoutError генерируется, если время простоя сценария достигает 15 секунд. Перехват исключения ScriptTimeoutError позволяет решить проблему простоя сценария более корректно. При отсутствии обработчика исключения обработчик необработанных исключений откроет диалоговое окно с сообщением об ошибке.
Для предотвращения преднамеренного перехвата исключения с созданием бесконечного цикла только первое исключение, генерируемое в рамках определенного сценария, может быть перехвачено. Последующее исключение ScriptTimeoutError не может быть перехвачено кодом разработчика и немедленно отправляется к обработчику необработанных исключений.
StackOverflowError Исключение StackOverflowError генерируется, если стек, доступный для сценария, полностью использован.
Исключение StackOverflowError может указывать на возникновение бесконечной рекурсии. Файл Описание
CustomErrors.mxml
или
CustomErrors.fla
Основной файл приложения Flash (FLA) или Flex (MXML)
com/example/programmingas3/errors/ApplicationError.as Класс, который служит базой для классов FatalError и WarningError.
Имя класса Описание Примечания
216
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Рассмотрение приложения CustomErrors
При загрузке приложения вызывается метод initApp()
в Flex или выполняется код временной шкалы (при отсутствии функций) в Flash. Этот код определяет образец пакета XML, который будет подтвержден классом Validator. Выполняется следующий код:
employeeXML = <employee id="12345"> <firstName>John</firstName> <lastName>Doe</lastName> <costCenter>12345</costCenter> <costCenter>67890</costCenter> </employee>; }
Пакет XML позже отображается в экземпляре компонента TextArea в рабочей области. Это позволяет модифицировать пакет XML перед попыткой его повторного подтверждения. При нажатии кнопки Validate (Подтвердить) вызывается метод validateData()
. Этот метод проверяет служебный пакет XML (список служащих) с помощью метода validateEmployeeXML()
класса Validator. Следующий код демонстрирует метод validateData()
:
function validateData():void { try { var tempXML:XML = XML(xmlText.text); Validator.validateEmployeeXML(tempXML); status.text = "The XML was successfully validated."; } catch (error:FatalError) { showFatalError(error); } catch (error:WarningError) { showWarningError(error); } catch (error:Error) { showGenericError(error); } }
com/example/programmingas3/errors/FatalError.as Класс, определяющий ошибку FatalError, которую может генерировать данное приложение. Этот класс расширяет пользовательский класс ApplicationError.
com/example/programmingas3/errors/Validator.as Класс, определяющий отдельный метод, который подтверждает поставляемый пользователем служебный пакет XML.
com/example/programmingas3/errors/WarningError.as Класс, определяющий ошибку WarningError, которую может генерировать данное приложение. Этот класс расширяет пользовательский класс ApplicationError.
Файл Описание
217
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Прежде всего, создается временный объект XML с помощью содержимого экземпляра компонента TextArea — xmlText
. Затем вызывается метод validateEmployeeXML()
в пользовательском классе Validator com.example.programmingas3/errors/Validator.as), который передает временный объект XML в качестве параметра. Если пакет XML оказывается действительным, экземпляр status
компонента Label отображает подтверждающее сообщение, и приложение закрывается. Если метод validateEmployeeXML()
генерирует пользовательскую ошибку (то есть FatalError, WarningError или базовую ошибку Error), выполняется соответствующая инструкция catch , которая вызывает один из следующих методов: showFatalError()
, showWarningError()
или showGenericError()
. Каждый из этих методов отображает в текстовой области с именем statusText
соответствующее сообщение для уведомления пользователя о возникновении специфической ошибки. Каждый метод обновляет также экземпляр status
компонента Label специальным сообщением.
Если при попытке подтверждения служебного пакета XML происходит фатальная ошибка, в текстовой области statusText
отображается сообщение об ошибке, а экземпляр xmlText
компонента TextArea и экземпляр validateBtn
компонента Button отключаются, как показано в следующем коде:
function showFatalError(error:FatalError):void { var message:String = error.message + "\n\n"; var title:String = error.getTitle(); statusText.text = message + " " + title + "\n\nThis application has ended."; this.xmlText.enabled = false; this.validateBtn.enabled = false; hideButtons(); }
Если вместо фатальной ошибки происходит предупреждающая ошибка, в текстовой области statusText
также отображается сообщение об ошибке, но экземпляры компонентов TextArea (
xmlText
) и Button не отключаются. Метод showWarningError()
отображает сообщение о пользовательской ошибке в текстовой области statusText
. В сообщении также предлагается пользователю сделать выбор: продолжить подтверждение XML или прекратить выполнение сценария. Следующий фрагмент демонстрирует метод showWarningError()
:
function showWarningError(error:WarningError):void { var message:String = error.message + "\n\n" + "Do you want to exit this application?"; showButtons(); var title:String = error.getTitle(); statusText.text = message; }
Метод closeHandler()
вызывается при нажатии кнопок «Да» или «Нет». Следующий фрагмент демонстрирует метод closeHandler()
:
218
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
function closeHandler(event:CloseEvent):void { switch (event.detail) { case yesButton: showFatalError(new FatalError(9999)); break; case noButton: statusText.text = ""; hideButtons(); break; } }
Если пользователь решает прекратить выполнение сценария нажатием кнопки «Да», генерируется фатальная ошибка FatalError, что приводит к закрытию приложения.
Создание пользовательского валидатора
Пользовательский класс Validator содержит один метод validateEmployeeXML()
. Метод validateEmployeeXML()
использует один аргумент employee
, который представляет собой проверяемый пакет XML. Метод validateEmployeeXML()
имеет следующую структуру:
public static function validateEmployeeXML(employee:XML):void { // checks for the integrity of items in the XML if (employee.costCenter.length() < 1) { throw new FatalError(9000); } if (employee.costCenter.length() > 1) { throw new WarningError(9001); } if (employee.ssn.length() != 1) { throw new FatalError(9002); } }
Для утверждения служащий должен принадлежать к одному (и только одному) центру учета затрат. Если служащий не принадлежит ни к одному центру учета затрат, метод генерирует неустранимую ошибку FatalError, которая передается методу validateData()
в главном файле приложения. Если служащий принадлежит к нескольким центрам учета затрат, генерируется предупреждающая ошибка WarningError. Окончательная проверка в валидаторе XML приводит к тому, что пользователь получает только один номер социального страхования (узел ssn
в пакете XML). Если обнаружить только один узел ssn
не удается, генерируется фатальная ошибка FatalError.
К методу validateEmployeeXML()
можно добавить дополнительные проверки. Например, подтверждение того, что узел ssn
содержит действительный номер или что служащий имеет хотя бы один телефонный номер и адрес электронной почты, а также, что оба значения являются действительными. Можно также модифицировать XML таким образом, что каждый служащий и его менеджер будут иметь уникальные идентификационные номера.
219
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
Определение класса ApplicationError
Класс ApplicationError служит основой для классов FatalError и WarningError. Класс ApplicationError является расширением класса Error. Он определяет свои специальные методы и свойства, включая идентификаторы ошибок и степень их серьезности, а также объект XML, содержащий коды и сообщения пользовательских ошибок. Этот класс также включает две статические постоянные, которые используются для определения степени серьезности для каждого типа ошибок.
Метод конструктора класса ApplicationError имеет следующую структуру:
public function ApplicationError() { messages = <errors> <error code="9000"> <![CDATA[Employee must be assigned to a cost center.]]> </error> <error code="9001"> <![CDATA[Employee must be assigned to only one cost center.]]> </error> <error code="9002"> <![CDATA[Employee must have one and only one SSN.]]> </error> <error code="9999"> <![CDATA[The application has been stopped.]]> </error> </errors>; }
Каждый узел ошибки в объекте XML содержит уникальный числовой код и сообщение об ошибке. Сообщения об ошибках легко просмотреть по их коду с помощью E4X, как показано в следующем методе getMessageText()
:
public function getMessageText(id:int):String { var message:XMLList = messages.error.(@code == id); return message[0].text(); }
Метод getMessageText()
принимает один целочисленный аргумент id
и возвращает строку. Аргумент id
является кодом ошибки, по которому эту ошибку можно найти. Например, поиск по id
9001 выдает ошибку, в сообщении которой говорится, что каждый служащий должен приписываться только к одному центру учета затрат. Если несколько ошибок имеют одинаковый код, ActionScript возвращает сообщение об ошибке только для первого найденного результата (
message[0]
в возвращенном объекте XMLList).
Следующий метод в этом классе, а именно getTitle()
, не принимает никаких параметров и возвращает строковое значение, содержащее идентификатор для данной специфической ошибки. Это значение позволяет пользователю легко определить, какая именно ошибка произошла в процессе проверки пакета XML. Следующий фрагмент демонстрирует метод getTitle()
:
public function getTitle():String { return "Error #" + id; }
Последним методом в классе ApplicationError является toString(). Этот метод заменяет функцию, определенную в классе Error, позволяя настроить передачу сообщения об ошибке. Этот метод возвращает строку, которая определяет номер специфической ошибки и сообщение о том, что произошло.
220
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Обработка ошибок
public override function toString():String { return "[APPLICATION ERROR #" + id + "] " + message; }
Определение класса FatalError
Класс FatalError является расширением пользовательского класса ApplicationError. Он определяет три метода: конструктор FatalError, getTitle()
и toString()
. Первый метод, конструктор FatalError, принимает один целочисленный аргумент, errorID
, задает степень серьезности ошибки с помощью значений статической постоянной, определенной в классе ApplicationError, и получает сообщение о специфической ошибке, вызывая метод getMessageText()
класса ApplicationError. Конструктор FatalError имеет следующую структуру:
public function FatalError(errorID:int) { id = errorID; severity = ApplicationError.FATAL; message = getMessageText(errorID); }
Следующий метод в классе FatalError, getTitle()
, заменяет метод getTitle()
, определенный ранее в классе ApplicationError, и дополняет текст заголовком «FATAL», уведомляя таким образом пользователя о фатальной ошибке. Метод getTitle()
имеет следующую структуру:
public override function getTitle():String { return "Error #" + id + " -- FATAL"; }
Последний метод в этом классе, toString()
, заменяет метод toString()
, определенный в классе ApplicationError. Метод toString()
имеет следующую структуру: public override function toString():String { return "[FATAL ERROR #" + id + "] " + message; }
Определение класса WarningError
Класс WarningError является расширением класса ApplicationError. Он практически идентичен классу FatalError, за исключением пары небольших изменений в строках и установки серьезности ошибки ApplicationError.WARNING вместо ApplicationError.FATAL, как показано в следующем коде:
public function WarningError(errorID:int) { id = errorID; severity = ApplicationError.WARNING; message = super.getMessageText(errorID); }
221
Глава 10. Использование регулярных выражений
Регулярное выражение описывает образец, используемый для нахождения в строках совпадающего текста и управления им. Регулярные выражения похожи на строки, но отличие в том, что они могут иметь особые коды для описания образцов и повторений. Например, следующее регулярное выражение сопоставляет строки, начинающиеся с символа А, за которым следует одна или несколько последовательных цифр:
/A\d+/
В этой главе описывается основной синтаксис, используемый для построения регулярных выражений. Однако с регулярными выражениями может быть связано много сложностей и нюансов. Подробные сведения о регулярных выражениях можно найти в Интернете и печатных изданиях. Следует помнить о том, что разные среды программирования по-разному работают с регулярными выражениями. ActionScript 3.0 работает с регулярными выражениями согласно определению, данному в спецификации к языку ECMAScript версии 3 (ECMA-262).
Основы регулярных выражений
Введение в использование регулярных выражений
Регулярное выражение описывает образец символов. Регулярные выражения обычно используются для проверки соответствия текстового значения определенному образцу (как, например, проверка наличия в телефонном номере, набранном пользователем, правильного числа цифр) или для замены частей текстового значения, соответствующих определенному образцу.
Регулярные выражения могут быть простыми. Например, предположим, что требуется подтвердить, что определенная строка соответствует «ABC», или заменить каждое появление в строке «ABC» другим текстом. В этом случае можно использовать следующее регулярное выражение, определяющее образец, состоящий из букв A, B и C, следующих друг за другом:
/ABC/
Следует отметить, что литерал регулярного выражения отделяется символом прямой косой черты /
.
Образцы регулярных выражений также могут быть сложными и иногда имеют зашифрованный вид, как, например, у следующего выражения, что в данном случае необходимо для подбора допустимого адреса электронной почты:
/([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}/
Чаще всего регулярные выражения используются для поиска образцов в строках и замены символов. В таких случаях создается объект регулярного выражения и используется в качестве параметра для одного или нескольких методов класса String. Следующие методы класса String используют регулярные выражения в качестве параметров: match()
, replace()
,
search()
и split()
. Дополнительные сведения об этих методах см. в разделе «Поиск шаблонов в строках и замена подстрок» на странице 159.
222
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Класс RegExp включает следующие методы: test()
и exec()
. Дополнительные сведения см. в разделе «Методы для использования регулярных выражений со строками» на странице 236.
Обычные задачи регулярных выражений
Существует несколько обычных применений регулярных выражений; эти случаи применения подробно описаны в данной главе.
•
Создание образца регулярного выражения.
•
Использование в образцах особых символов.
•
Определение последовательности нескольких символов (таких как «двузначное число» или «между седьмой и десятой буквами»)
•
Определение любого символа из множества букв или чисел (как, например, «любая буква от a до m» ).
•
Определение символа в наборе возможных символов
•
Определение подпоследовательности (сегменты внутри образца)
•
Сопоставление и замена текста на основе образцов
Важные понятия и термины
Ниже приводится список важных терминов, которые используются в данной главе.
•
Символ перехода: символ, указывающий на то, что последующий символ должен рассматриваться как метасимвол, а не как символ литерала. В синтаксисе регулярного выражения символом перехода является обратная косая черта (
\
), поэтому обратная косая черта, после которой идет другой символ, является особым кодом, а не просто символом.
•
Флаг: символ, указывающий вариант использования образца регулярного выражения, как, например, необходимость в различии между символами верхнего и нижнего регистров.
•
Метасимвол: символ, имеющий особое значение в образце регулярного выражения в отличие от буквального представления данного символа в образце.
•
Квантификатор: символ (или несколько символов), указывающий число повторений части образца. Например, квантификатор может использоваться для обозначения того, что почтовый индекс Соединенных Штатов должен содержать пять или девять чисел.
•
Регулярное выражение: инструкция программы, определяющая образец символов, используемый для подтверждения совпадения других строк данному образцу или для замены частей строки.
Работа с примерами из главы
Прорабатывая главу, вы можете самостоятельно тестировать приведенные в ней примеры кодов. Поскольку в данной главе списки кодов состоят в основном из образцов регулярных выражений, проверка примеров включает несколько этапов.
1
Создайте новый документ Flash.
2
Выбор ключевого кадра и открытие панели «Действия».
3
Создание переменной (регулярного выражения) RegExp, такой как эта:
var pattern:RegExp = /ABC/;
223
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
4
Копирование образца из примера и назначение его в качестве значения переменной RegExp. Например, в предыдущей строке кода образец является частью кода справа от знака равенства, исключая точку с запятой (
/ABC/
).
5
Создание одной или нескольких переменных String, содержащих строки, предназначенные для проверки регулярного выражения. Например, при создании регулярного выражения для проверки допустимости адресов электронной почты создайте несколько переменных String, содержащих допустимые и недопустимые адреса электронной почты:
var goodEmail:String = "bob@example.com"; var badEmail:String = "5@$2.99";
6
Добавление строк кода для проверки переменных String на установление наличия или отсутствия соответствия образцу регулярного выражения. Это будут значения, которые потребуется вывести на экран с помощью функции trace()
или путем записи их в текстовое поле в рабочей области.
trace(goodEmail, " is valid:", pattern.test(goodEmail)); trace(badEmail, " is valid:", pattern.test(badEmail));
Например, предположим, что pattern
определяет образец регулярного выражения для допустимого адреса электронной почты, предшествующие строки кода записывают этот текст на панели «Вывод»:
bob@example.com is valid: true 5@$2.99 is valid: false
Дополнительные сведения о проверке значений путем записи этих значений в экземпляр текстового поля в рабочей области или путем использования функции trace()
с целью печати значений на панели «Вывод» см. в разделе «Тестирование примеров кода» на странице 38.
Синтаксис регулярных выражений
В данном разделе описываются все элементы синтаксиса регулярных выражений ActionScript. Как будет видно далее, с регулярными выражениями может быть связано много сложностей и нюансов. Подробные сведения о регулярных выражениях можно найти в Интернете и печатных изданиях. Следует помнить о том, что разные среды программирования по-разному работают с регулярными выражениями. ActionScript 3.0 работает с регулярными выражениями согласно определению, данному в спецификации к языку ECMAScript версии 3 (ECMA-262).
Обычно используются регулярные выражения, соответствующие более сложным образцам, чем простая строка символов. Например, следующее регулярное выражение определяет образец, состоящий из букв A, B и C, следующих друг за другом и имеющих после себя любую цифру:
/ABC\d/
Код \d
обозначает «любую цифру». Символ обратной косой черты (
\
) называется символом перехода и в сочетании с символом, следующим за ним (в данном случае это буква d), имеет в регулярном выражении особое значение. В данной главе описываются последовательности этих символов перехода, а также другие возможности синтаксиса регулярных выражений. Следующее регулярное выражение определяет образец букв ABC, за которыми следует любое число цифр (обратите внимание на наличие звездочки):
/ABC\d*/
224
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Символ звездочки (
*
) является метасимволом. Метасимвол представляет собой символ, имеющий в регулярном выражении особое значение. Звездочка является особым типом метасимвола, называемым квантификатор и используемым с целью определения количества повторений символа или группы символов. Более подробно об этом см. в разделе «Квантификаторы» на странице 229.
Помимо образца в состав регулярного выражения могут входить флаги, которые определяют способ сопоставления регулярного выражения. Например, в следующем регулярном выражении используется флаг i
, который указывает на то, что данное регулярное выражение при сопоставлении строк не учитывает регистр.
/ABC\d*/i
Более подробно об этом см. в разделе «Флаги и свойства» на странице 233.
Регулярные выражения можно использовать со следующими методами класса String: match()
, replace()
и search()
. Дополнительные сведения об этих методах см. в разделе «Поиск шаблонов в строках и замена подстрок» на странице 159.
Создание экземпляра регулярного выражения
Экземпляр регулярного выражения можно создать двумя способами. При одном способе для разделения регулярного выражения используется символ прямой косой черты (
/
), при другом — конструктор new
. Например, эквивалентными являются следующие регулярные выражения:
var pattern1:RegExp = /bob/i; var pattern2:RegExp = new RegExp("bob", "i");
Прямые косые черты отделяют регулярное выражение так же, как кавычки отделяют строковый литерал. Часть регулярного выражения, находящаяся внутри прямых косых черт, определяет образец. Регулярное выражение также может иметь в своем составе флаги, расположенные после конечной отделяющей черты. Эти флаги считаются частью регулярного выражения, но отделены от его образца. При использовании конструктора new
для определения регулярного выражения используются две строки. Первая строка определяет образец, а вторая строка — флаги, как показано в следующем примере:
var pattern2:RegExp = new RegExp("bob", "i");
При включении прямой косой черты в состав регулярного выражения, определенного использованием ограничителей прямой косой черты, прямой косой черте должен предшествовать символ перехода (
\
) обратной косой черты. Например, образцу 1/2
соответствует следующее регулярное выражение:
var pattern:RegExp = /1\/2/;
Чтобы включить кавычки в состав регулярного выражения, определенного конструктором new
, перед кавычками необходимо добавить символ перехода
\
обратной косой черты (так же, как при определении любого строкового литерала). Например, образцу eat at "joe's"
соответствуют следующие регулярные выражения:
var pattern1:RegExp = new RegExp("eat at \"joe's\"", ""); var pattern2:RegExp = new RegExp('eat at "joe\'s"', "");
В регулярных выражениях, определяемых использованием ограничителей прямой косой черты, не используйте символ обратной косой черты с кавычками. Аналогичным образом, в регулярных выражениях, определяемых конструктором new
, не используйте символ перехода с прямыми косыми чертами. Следующие регулярные выражения эквивалентны; они определяют образец 1/2 "joe's"
:
var pattern1:RegExp = /1\/2 "joe's"/; var pattern2:RegExp = new RegExp("1/2 \"joe's\"", ""); var pattern3:RegExp = new RegExp('1/2 "joe\'s"', '');
225
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Также в регулярном выражении, которое определяется конструктором new
, чтобы воспользоваться метапоследовательностью, которая начинается с символа обратной косой черты (
\
) (например, \d
, что соответствует любой цифре), дважды введите символ обратной косой черты:
var pattern:RegExp = new RegExp("\\d+", ""); // matches one or more digits
В данном случае необходимо ввести символ обратной косой черты дважды, поскольку первый параметр метода конструктора RegExp()
является строкой. В строковом литерале также необходимо дважды ввести символ обратной косой черты, чтобы он распознавался как единичный символ.
В разделах, приведенных ниже, описывается синтаксис для определения образцов регулярных выражений.
Дополнительные сведения о флагах см. в разделе «Флаги и свойства» на странице 233.
Символы, метасимволы и метапоследовательности
Самым простым регулярным выражением является такое выражение, последовательность символов которого соответствует последовательности, указанной в следующем примере:
var pattern:RegExp = /hello/;
Однако следующие символы, известные как метасимволы ,, имеют в регулярных выражениях особое значение:
^ $ \ . * + ? ( ) [ ] { } |
Например, следующее регулярное выражение соответствует букве А, за которой следует нуль или несколько экземпляров буквы B (метасимвол звездочки обозначает это повторение), за которыми, в свою очередь, идет буква C:
/AB*C/
Чтобы в образец регулярного выражения добавить метасимвол без его особого значения, необходимо использовать символ перехода \
обратной косой черты. Например, следующее регулярное выражение соответствует букве А, за которой следует буква B, за которой идет звездочка, за которой, в свою очередь, идет буква C:
var pattern:RegExp = /AB\*C/;
Метапоследовательность, как и метасимвол, имеет в регулярном выражении особое значение. Метапоследовательность состоит из более чем одного символа. В следующих разделах подробно описывается использование метасимволов и метапоследовательностей.
О метасимволах В следующей таблице собраны метасимволы, которые могут быть использованы в регулярных выражениях. 226
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Метасимвол Описание
^
(знак вставки) Соответствует началу строки. Вместе с установленным флагом m
(
multiline
) знак вставки также соответствует началу строки (см. раздел «Флаги и свойства» на странице 233). Обратите внимание, что знак вставки при использовании в начале класса символов обозначает отрицание, а не начало строки. Более подробно об этом см. в разделе «Классы символов» на странице 227.
$
(знак доллара) Соответствует концу строки. Вместе с установленным флагом m
(
multiline
) знак $
также соответствует положению перед символом (
\n
) новой строки. Более подробно об этом см. в разделе «Флаги и свойства» на странице 233.
\
(обратная косая черта) Обозначает переход от особого значения метасимвола особых символов. Символ обратной косой черты также применяется, если в литерале регулярного выражения нужно использовать символ прямой косой черты, как показано далее /1\/2/
(чтобы соответствовать символу 1, за которым следует символ прямой косой черты, за которым идет символ 2).
.
(точка) Соответствует любому одиночному символу. Точка соответствует символу новой строки (
\n
), только если установлен флаг s
(
dotall
). Более подробно об этом см. в разделе «Флаги и свойства» на странице 233. *
(звезда) Соответствует предыдущему элементу, повторяющемуся нуль или более раз. Более подробно об этом см. в разделе «Квантификаторы» на странице 229.
+
(плюс) Соответствует предыдущему элементу, повторяющемуся один или более раз. Более подробно об этом см. в разделе «Квантификаторы» на странице 229.
?
(знак вопроса) Соответствует предыдущему элементу, повторяющемуся нуль или один раз. Более подробно об этом см. в разделе «Квантификаторы» на странице 229.
(
и ) Определяет группы внутри регулярного выражения. Группы используются со следующей целью.
•
Для ограничения области оператора перестановок | : /(a|b|c)d/
•
Для определения области квантификатора: /(walla.){1,2}/
•
Во встречных ссылках. Например, в следующем регулярном выражении \1
соответствует всему, что соответствует первой группе образца в круглых скобках: •
/(\w*) is repeated: \1/
Более подробно об этом см. в разделе «Группы» на странице 230.
[
и ] Определяет класс символов, определяющий возможные совпадения для одиночного символа:
/[aeiou]/
соответствует любому из указанных символов.
Дефис (
-
) используется внутри классов символов для обозначения диапазона символов:
/[A-Z0-9]/
соответствует буквам верхнего регистра от А до Z или цифрам от 0 до 9.
Внутри классов символов для перехода от символов ] и - используется вставка обратной косой черты:
/[+\-]\d+/
соответствует либо +
, либо -
перед одной или несколькими цифрами.
Внутри классов символов другие символы, которые обычно являются метасимволами, рассматриваются как обычные символы (не метасимволы), избегая необходимости использовать обратную косую черту:
/[$]/
£ соответствует либо $
, либо £
.
Более подробно об этом см. в разделе «Классы символов» на странице 227.
|
(вертикальная черта) Используется для перестановок, чтобы соответствовать либо части справа, либо части слева:
/abc|xyz/
соответствует либо abc
, либо xyz
.
227
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
О метапоследовательностях
Метапоследовательности представляют собой последовательности символов, имеющих в образце регулярного выражения особое значение. В следующей таблице приведено описание этих метапоследовательностей.
Классы символов
Классы символов используются для установления списка символов и их соответствий определенной позиции в регулярном выражении. Классы символов определяются с помощью квадратных скобок ( [
и ]
). Например, следующее регулярное выражение определяет класс символов, соответствующий bag
, beg
, big
, bog
или bug
:
/b[aeiou]g/
Метапоследовательность Описание
{n}
{n,}
и
{n,n}
Определяет числовой квантификатор или диапазон квантификатора предыдущего элемента: /A{27}/
соответствует символу ?
, повторяемому 27
раз.
/A{3,}/
соответствует символу ?
, повторяемому 3
раза или более.
/A{3,5}/
соответствует символу ?
, повторяемому от 3
до 5
раз.
Более подробно об этом см. в разделе «Квантификаторы» на странице 229.
\b
Соответствует положению между словесным символом и несловесным символом. Также соответствует началу или концу строки, если первый или последний символ в строке является словесным символом.
\B
Соответствует положению между двумя словесными символами. Также соответствует положению между двумя несловесными символами.
\d
Соответствует десятичной цифре.
\D
Соответствует любому символу, отличному от цифры.
\f
Соответствует символу перевода страницы.
\n
Соответствует символу начала строки.
\r
Соответствует символу возврата.
\s
Соответствует любому символу разделителя (символу пробела, табуляции, новой строки или возврата).
\S
Соответствует любому символу, отличному от символа разделителя.
\t
Соответствует символу табуляции.
\unnnn
Соответствует символу юникода с кодом символа, заданным шестнадцатеричным числом nnnn. Например, \u263a
является символом смайлика.
\v
Соответствует символу вертикальной подачи.
\w
Соответствует словесному символу (
AZ
–, az
–, 0-9
или _
). Следует отметить, что \w
не соответствует символам, не являющимся символами английского языка, таким как é , ñ или ç
.
\W
Соответствует любому символу, отличному от словесного символа.
\\xnn
Соответствует символу с заданным значением ASCII, определенным шестнадцатеричным числом nn.
228
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Переход последовательностей в классах символов
Большинство метасимволов и метапоследовательностей, обычно имеющих в регулярном выражении особое значение, не сохраняют это значение внутри класса символов. Например, звездочка используется в регулярном выражении для обозначения повторения, но это не так, когда звездочка появляется в классе символов. Следующий класс символов буквально соответствует звездочке наряду с любым из перечисленных символов:
/[abc*123]/
Однако три символа, приведенные в следующей таблице, действительно функционируют как метасимволы, сохраняя в классах символов особое значение.
Чтобы каждый из этих символов распознавался как символ литерала (без особого значения метасимвола), необходимо поставить перед этим символом символ перехода обратной косой черты. Например, следующее регулярное выражение включает класс символов, соответствующий любому из четырех символов (
$
, \
, ]
или -
):
/[$\\\]\-]/
Помимо метасимволов, сохраняющих свое особое значение, следующие метапоследовательности функционируют как метапоследовательности внутри классов символов:
Другие метапоследовательности и метасимволы регулярных выражений рассматриваются внутри класса символов как обычные символы. Диапазоны символов в классах символов
Дефис используется для определения диапазона символов, как например A-Z
, a-z
или 0-9
. Эти символы должны составлять допустимый диапазон в наборе символов. Например, следующий класс символов соответствует любому из символов диапазона a-z
или любой цифре:
/[a-z0-9]/
Для определения диапазона значения ASCII можно также использовать код символа ASCII \\x
nn. Например, следующий класс символов соответствует любому символу из набора расширенных символов ASCII (таких как é и ê ):
\\x
Метасимвол Значение в классах символов
]
Определяет конец класса символов.
-
Определяет диапазон символов (см. следующий раздел «Диапазоны символов в классах символов»).
\
Определяет метапоследовательности и отменяет особое значение метасимволов. Метапоследовательность Значение в классах символов
\n
Соответствует символу начала строки.
\r
Соответствует символу возврата.
\t
Соответствует символу табуляции.
\unnnn
Соответствует символу с заданным значением точки кода юникод (определенным шестнадцатеричным числом nnnn).
\\xnn
Соответствует символу с заданным значением ASCII (определенным шестнадцатеричным числом nn).
229
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Классы символов с отрицанием
При использовании в начале класса символов символа (
^
) вставки он отрицает этот класс — любой неперечисленный символ рассматривается как совпадение. Следующий класс символов соответствует любому символу, за исключением буквы нижнего регистра (
az
–) или цифры:
/[^a-z0-9]/
Для обозначения отрицания необходимо поставить символ (
^
) вставки в начале класса символов. Иначе символ вставки просто добавляется к символам в классе символов. Например, следующий класс символов соответствует любому из числа символов, включая символ вставки:
/[!.,#+*%$&^]/
Квантификаторы
Квантификаторы используются для определения повторений символов или последовательностей в образце, как показано далее.
Квантификатор может применяться в отношении одиночного символа, класса символов или группы:
•
/a+/
соответствует символу a
, повторяемому один раз или более.
•
/\d+/
соответствует одной или нескольким цифрам.
•
/[abc]+/
соответствует повторению одного или более символов, каждый из которых является либо
a
, либо b
, либо c
.
•
/(very, )*/
соответствует слову very
, за которым следует запятая и пробел, повторяемый нуль раз или более.
Квантификаторы могут использоваться внутри групп в круглых скобках, имеющих применимые к ним квантификаторы. Например, следующий квантификатор соответствует строкам, таким как word
и word-word-word
:
/\w+(-\w+)*/
По умолчанию регулярные выражения представляют то, что известно как поглощающее совпадение. Любой подобразец в регулярном выражении (таком как .*
пытается соответствовать как можно большему числу символов в строке, прежде чем переходить к следующей части регулярного выражения. Например, рассмотрим следующее регулярное выражение и строку:
var pattern:RegExp = /<p>.*<\/p>/; str:String = "<p>Paragraph 1</p> <p>Paragraph 2</p>";
Регулярное выражение соответствует всей строке: <p>Paragraph 1</p> <p>Paragraph 2</p>
Метасимвол квантификатора
Описание
*
(звезда) Соответствует предыдущему элементу, повторяющемуся нуль или более раз. +
(плюс) Соответствует предыдущему элементу, повторяющемуся один или более раз. ?
(знак вопроса) Соответствует предыдущему элементу, повторяющемуся нуль или один раз. {n}
{n,}
и
{n,n}
Определяет числовой квантификатор или диапазон квантификатора предыдущего элемента: /A{27}/
соответствует символу А, повторяемому 27 раз.
/A{3,}/
соответствует символу А, повторяемому 3 раза или более.
/A{3,5}/
соответствует символу А, повторяемому от 3 до 5 раз.
230
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Хотя предположим, что требуется соответствие только одной группе <p>...</p>
. Это можно сделать следующим образом:
<p>Paragraph 1</p>
Добавьте знак вопроса (
?
после любого квантификатора, чтобы изменить его на то, что известно как «ленивый» квантификатор. Например, следующее регулярное выражение, использующее «ленивый» квантификатор *? , соответствует <p>
, за которым следует минимально возможное число («ленивых») символов, за которыми идет </p>
:
/<p>.*?<\/p>/
Следует держать в памяти следующие пункты, касающиеся квантификаторов.
•
Квантификаторы {0}
и {0,0}
не исключают из совпадения элемент.
•
Не объединяйте несколько квантификаторов, как в /abc+*/
.
•
Символ точки (.) не соединяет строки до тех пор, пока не установлен флаг s
(
dotall
), даже если за ним идет квантификатор *
. Например, рассмотрим следующий код:
var str:String = "<p>Test\n"; str += "Multiline</p>"; var re:RegExp = /<p>.*<\/p>/; trace(str.match(re)); // null; re = /<p>.*<\/p>/s; trace(str.match(re)); // output: <p>Test //Multiline</p>
Более подробно об этом см. в разделе «Флаги и свойства» на странице 233.
Перестановки
Символ вертикальной черты (
|
) используется в регулярных выражениях с той целью, чтобы механизм регулярного выражения учитывал при совпадении альтернативные варианты. Например, следующее регулярное выражение соответствует любому из представленных слов cat, dog, pig, rat
:
var pattern:RegExp = /cat|dog|pig|rat/;
Можно использовать круглые скобки для определения групп с целью ограничения области оператора перестановок |. Следующее регулярное выражение соответствует слову cat
, за которым идет nap
или nip
.
var pattern:RegExp = /cat(nap|nip)/;
Более подробно об этом см. в разделе «Группы» на странице 230.
Два следующих регулярных выражения, в одном из которых используется оператор перестановок |
, а в другом — класс символов (определенный [
и ]
), эквивалентны.
/1|3|5|7|9/ /[13579]/
Более подробно об этом см. в разделе «Классы символов» на странице 227.
Группы
Группу в регулярном выражении можно определить с помощью круглых скобок следующим образом:
/class-(\d*)/
231
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Группа является подразделом образца. Группы можно использовать со следующей целью.
•
Для применения квантификатора к нескольким символам.
•
Для отделения подобразцов с целью применения при перестановках (с помощью символа |
).
•
Для сбора совпадений подстрок (к примеру, с помощью использования \1
в регулярных выражениях для подбора ранее сопоставленной группы или с помощью применения $1
аналогичным образом в методе replace()
класса String).
В следующих разделах подробно описывается использование таких групп.
Использование групп с квалификаторами
Если группа не используется, квантификатор применяется к символу или классу символов, предшествующих ему, как это показано далее:
var pattern:RegExp = /ab*/ ; // matches the character a followed by // zero or more occurrences of the character b pattern = /a\d+/; // matches the character a followed by // one or more digits pattern = /a[123]{1,3}/; // matches the character a followed by // one to three occurrences of either 1, 2, or 3
Однако можно использовать группу для применения квантификатора к нескольким символам или классам символов:
var pattern:RegExp = /(ab)*/; // matches zero or more occurrences of the character a // followed by the character b, such as ababab pattern = /(a\d)+/; // matches one or more occurrences of the character a followed by // a digit, such as a1a5a8a3 pattern = /(spam ){1,3}/; // matches 1 to 3 occurrences of the word spam followed by a space
Более подробно об этом см. в разделе «Квантификаторы» на странице 229.
Использование групп с символом оператора перестановок (|)
Группы можно использовать для определения групп символов, к которым требуется применить символ оператора перестановок |
), как показано ниже:
var pattern:RegExp = /cat|dog/; // matches cat or dog pattern = /ca(t|d)og/; // matches catog or cadog
232
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Использование групп для сбора совпадений подстрок
При определении в образце стандартной группы в круглых скобках можно позднее сослаться на нее в регулярном выражении. Такой прием известен под названием обратная ссылка, а такие виды групп известны как группы сбора. Например, в следующем регулярном выражении последовательность \1
соответствует всему, чему соответствует подстрока группы в круглых скобках:
var pattern:RegExp = /(\d+)-by-\1/; // matches the following: 48-by-48
В регулярном выражении можно указать до 99 таких обратных ссылок, напечатав \1
, \2
, ... , \99
. Аналогичным образом в методе replace()
класса String можно использовать $1$99
для вставки в замещающую цепочку собранных совпадений подстрок группы:
var pattern:RegExp = /Hi, (\w+)\./; var str:String = "Hi, Bob."; trace(str.replace(pattern, "$1, hello.")); // output: Bob, hello.
Также при использовании групп сбора метод exec()
класса RegExp и метод match()
класса String возвращают подстроки, соответствующие группам сбора:
var pattern:RegExp = /(\w+)@(\w+).(\w+)/; var str:String = "bob@example.com"; trace(pattern.exec(str)); // bob@example.com,bob,example,com
Использование групп без сбора и групп просмотра вперед
Группой без сбора является группа, используемая только для образования групп, она не «собирает» и не совпадает с пронумерованными обратными ссылками. Используйте (?: и )
для определения групп без сбора, как показано далее:
var pattern = /(?:com|org|net);
Например, обратите внимание на разницу между использованием (com|org)
в группе сбора по сравнению с использованием в группе без сбора (метод exec()
дает перечень групп сбора после полного совпадения):
var pattern:RegExp = /(\w+)@(\w+).(com|org)/; var str:String = "bob@example.com"; trace(pattern.exec(str)); // bob@example.com,bob,example,com //noncapturing: var pattern:RegExp = /(\w+)@(\w+).(?:com|org)/; var str:String = "bob@example.com"; trace(pattern.exec(str)); // bob@example.com,bob,example
Особым типом группы без сбора является группа просмотра вперед, которая бывает двух типов: позитивная группа просмотра вперед и негативная группа просмотра вперед.
Используйте (?=
и )
для определения позитивной группы просмотра вперед, которая задает соответствие подобразца в группе определенному положению. Однако часть строки, соответствующая позитивной группе просмотра вперед, может соответствовать оставшимся образцам в регулярном выражении. Например, поскольку в следующем коде (?=e)
является позитивной группой просмотра вперед, символ e
, которому она соответствует, может совпадать с последующей частью регулярного выражения, в данном случае группой сбора \w*)
:
233
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
var pattern:RegExp = /sh(?=e)(\w*)/i; var str:String = "Shelly sells seashells by the seashore"; trace(pattern.exec(str)); // Shelly,elly
Используйте (?!
и )
для определения негативной группы просмотра вперед, которая задает отсутствие совпадения подобразца в группе определенному положению. Например:
var pattern:RegExp = /sh(?!e)(\w*)/i; var str:String = "She sells seashells by the seashore"; trace(pattern.exec(str)); // shore,ore
Использование именованных групп
Именованная группа является типом группы в регулярном выражении, которой дан именованный идентификатор. Используйте (?P<name> и )
для определения именованной группы. Например, в состав следующего регулярного выражения входит именованная группа с идентификатором под именем digits
:
var pattern = /[a-z]+(?P<digits>\d+)[a-z]+/;
При использовании метода exec()
добавляется совпадающая именованная группа в качестве свойства массива result
:
var myPattern:RegExp = /([a-z]+)(?P<digits>\d+)[a-z]+/; var str:String = "a123bcd"; var result:Array = myPattern.exec(str); trace(result.digits); // 123
Вот другой пример, в котором используются две именованных группы с идентификаторами name
и dom
:
var emailPattern:RegExp = /(?P<name>(\w|[_.\-])+)@(?P<dom>((\w|-)+))+\.\w{2,4}+/; var address:String = "bob@example.com"; var result:Array = emailPattern.exec(address); trace(result.name); // bob trace(result.dom); // example
Примечание. Именованные группы не являются частью спецификации языка ECMAScript. Они представляют собой добавленную в ActionScript 3.0 возможность.
Флаги и свойства
В следующей таблице представлены пять флагов, которые можно установить для регулярных выражений. Каждый флаг можно оценить как свойство объекта регулярного выражения. Флаг Свойство Описание
g global
Соответствует нескольким совпадениям.
i ignoreCase
Совпадение без учета регистра. Применяется к символам A
—
Z
и a
—
z
, но не к расширенным символам, таким как É и é .
m multiline
Когда этот флаг установлен, символы $
и ^
могут соответствовать началу и концу строки соответственно. s dotall
Когда этот флаг установлен, символ .
(точка) может соответствовать символу новой строки (
\n
).
x extended
Разрешает расширенные регулярные выражения. В состав регулярного выражения можно ввести пробелы, которые не рассматриваются как часть образца. Благодаря этому код регулярного выражения может быть более четким.
234
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Следует отметить, что эти свойства доступны только для чтения. Когда задается переменная регулярного выражения, установить флаги (
g
, i
, m
, s
, x
) можно следующим образом:
var re:RegExp = /abc/gimsx;
Однако именованные свойства нельзя задать напрямую. К примеру, следующий код привел к появлению ошибки:
var re:RegExp = /abc/; re.global = true; // This generates an error.
По умолчанию, пока они не будут заданы в объявлении регулярного выражения, флаги не будут установлены и соответствующие свойства будут также установлены на false
. Кроме того, существуют два других свойства регулярного выражения. •
Свойство lastIndex
определяет положение указателя в строке с целью использования для следующего вызова метода exec()
или test()
регулярного выражения. •
Свойство source
определяет строку, которая, в свою очередь, определяет часть образца регулярного выражения.
Флаг g (global)
Если флаг g
(
global
) не установлен, регулярное выражение имеет не более одного совпадения. Например, если в регулярном выражении флаг g
не установлен, метод String.match()
возвращает только одну совпадающую подстроку:
var str:String = "she sells seashells by the seashore."; var pattern:RegExp = /sh\w*/; trace(str.match(pattern)) // output: she
Если флаг g
установлен, метод Sting.match()
возвращает несколько совпадений, как показано далее:
var str:String = "she sells seashells by the seashore."; var pattern:RegExp = /sh\w*/g; // The same pattern, but this time the g flag IS set. trace(str.match(pattern)); // output: she,shells,shore
Флаг i (ignoreCase)
По умолчанию совпадения регулярных выражений учитывают регистр. Если установлен флаг i
(
ignoreCase
), регистр не учитывается. Например, в регулярных выражениях буква s
нижнего регистра не соответствует букве S
верхнего регистра, первому символу строки:
var str:String = "She sells seashells by the seashore."; trace(str.search(/sh/)); // output: 13 -- Not the first character
Однако, если установлен флаг i
, регулярное выражение не соответствует заглавной букве S
:
var str:String = "She sells seashells by the seashore."; trace(str.search(/sh/i)); // output: 0
Флаг i
не учитывает регистр только в случае с символами A
–
Z
и a
–
z
, за исключением расширенных символов, таких как É и é .
Флаг m (multiline)
Если флаг m
(
multiline
) не установлен, символ ^
соответствует началу строки, а символ $
— концу строки. Если флаг m
установлен, эти символы соответствуют началу и концу строки соответственно. Рассмотрим следующую строку, в состав которой входит символ начала строки:
235
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
var str:String = "Test\n"; str += "Multiline"; trace(str.match(/^\w*/g)); // Match a word at the beginning of the string.
Несмотря на то что в регулярном выражении установлен флаг g
(
global
), метод match()
соответствует только одной подстроке, поскольку для символа ^
существует только одно совпадение, которым является начало строки. Получены следующие результаты:
Test
Вот такой же код с установленным флагом m
:
var str:String = "Test\n"; str += "Multiline"; trace(str.match(/^\w*/gm)); // Match a word at the beginning of lines. В этот раз результат включает слова в начале обеих строк:
Test,Multiline
Следует отметить, что только символ \n
обозначает конец строки. Следующие символы не обозначают конец строки.
•
Символ (
\r
) возврата
•
Символ (
\u2028
) разделителя строк юникода
•
Символ (
\u2029
) разделителя абзацев юникода
Флаг s (dotall)
Если флаг s
(
dotall
или «dot all») не установлен, точка (
.
) в образце регулярного выражения не соответствует символу начала строки (
\n
). Поэтому для следующего примера совпадение отсутствует:
var str:String = "<p>Test\n"; str += "Multiline</p>"; var re:RegExp = /<p>.*?<\/p>/; trace(str.match(re)); Однако, если флаг s
установлен, точка соответствует символу начала строки:
var str:String = "<p>Test\n"; str += "Multiline</p>"; var re:RegExp = /<p>.*?<\/p>/s; trace(str.match(re)); В этом случае совпадением является вся подстрока внутри тегов <p>
, включая символ начала строки:
<p>Test Multiline</p>
Флаг x (extended)
При чтении регулярных выражений могут возникнуть трудности, особенно если в их составе много метасимволов и метапоследовательностей. Например:
/<p(>|(\s*[^>]*>)).*?<\/p>/gi
При использовании в регулярном выражении флага x
(
extended
) все пробелы, введенные в образец, игнорируются. Например, следующее регулярное выражение идентично предыдущему примеру:
/ <p (> | (\s* [^>]* >)) .*? <\/p> /gix
236
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Если флаг x
установлен и нет необходимости в совпадении символа пробела, поставьте перед пробелом обратную косую черту. Например, эквивалентными являются следующие два регулярных выражения:
/foo bar/ /foo \ bar/x
Свойство lastIndex
Свойство lastIndex
определяет позицию указателя в строке, с которой должен начинаться следующий поиск. Это свойство влияет на методы exec()
и test()
, вызываемые в регулярном выражении, в котором для флага g
установлено значение true
. Например, рассмотрим следующий код:
var pattern:RegExp = /p\w*/gi; var str:String = "Pedro Piper picked a peck of pickled peppers."; trace(pattern.lastIndex); var result:Object = pattern.exec(str); while (result != null) { trace(pattern.lastIndex); result = pattern.exec(str); }
По умолчанию для свойства lastIndex
установлено значение 0 (чтобы поиск начинался в начале строки). После каждого совпадения для свойства задается положение указателя, следующее за совпадением. Поэтому результат для предшествующего кода выглядит следующим образом:
0 5 11 18 25 36 44
Если для флага global
задано значение false
, методы exec()
и test() не используют свойство lastIndex
.
Методы match()
, replace()
и search()
класса String всегда начинают поиск с начала строки, несмотря на использование свойства lastIndex
регулярного выражения, применяемого при вызове метода. (Однако метод match()
не задает для свойства lastIndex
значение 0.)
Свойство lastIndex
можно установить так, чтобы скорректировать начальную позицию в строке для поиска совпадений регулярных выражений.
Свойство source
Свойство source
определяет строку, которая, в свою очередь, определяет часть образца регулярного выражения. Например:
var pattern:RegExp = /foo/gi; trace(pattern.source); // foo
Методы для использования регулярных выражений со строками
Класс RegExp включает два метода: exec()
и test()
.
237
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Помимо методов exec()
и test()
класса RegExp, класс String включает следующие методы, позволяющие сопоставлять регулярные выражения в строках: match()
, replace()
, search()
и splice()
.
Метод test()
Метод test()
класса RegExp просто проверяет предоставленные строки на предмет наличия совпадений регулярного выражения, как это показано в примере ниже:
var pattern:RegExp = /Class-\w/; var str = "Class-A"; trace(pattern.test(str)); // output: true
Метод exec()
Метод exec()
класса RegExp проверяет предоставленные строки на предмет наличия совпадения регулярного выражения и возвращает массив вместе со следующим.
•
Совпадающей подстрокой
•
Подстрока соответствует любой группе в круглых скобках регулярного выражения
Массив также включает свойство index
, определяющее положение указателя начала совпадения подстроки.
Например, рассмотрим следующий код:
var pattern:RegExp = /\d{3}\-\d{3}-\d{4}/; //U.S phone number var str:String = "phone: 415-555-1212"; var result:Array = pattern.exec(str); trace(result.index, " - ", result); // 7-415-555-1212
Если в регулярном выражении установлен флаг g
(
global
), несколько раз используйте метод exec()
для совпадения нескольких подстрок.
var pattern:RegExp = /\w*sh\w*/gi; var str:String = "She sells seashells by the seashore"; var result:Array = pattern.exec(str); while (result != null) { trace(result.index, "\t", pattern.lastIndex, "\t", result); result = pattern.exec(str); } //output: // 0 3 She // 10 19 seashells // 27 35 seashore
Методы String, использующие параметры RegExp
Следующие методы класса String используют регулярные выражения в качестве параметров: match()
, replace()
,
search()
и split()
. Дополнительные сведения об этих методах см. в разделе «Поиск шаблонов в строках и замена подстрок» на странице 159. 238
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Пример: синтаксический анализатор Wiki
Простой пример преобразования текста Wiki показывает ряд случаев применения регулярных выражений.
•
Преобразование строк текста, при котором происходит совпадение исходного образца Wiki с определенными выводными строками HTML.
•
Использование регулярного выражения с целью преобразования образцов URL в теги гиперссылок <a>
HTML.
•
Использование регулярного выражения с целью преобразования строк символа доллара США (таких как "$9.95"
) в строки символа евро (такие как "8.24 €"
).
Получить файлы с образцами применения приведенных случаев можно по адресу www.adobe.com/go/learn_programmingAS3samples_flash_ru. Файлы с образцами применения WikiEditor можно найти в папке Samples/WikiEditor. Приложение состоит из следующих файлов.
Определение класса WikiParser
Класс WikiParser включает методы, которые преобразуют вводимый текст Wiki в эквивалентный выводной текст HTML. Этот случай применения преобразования не является достаточно устойчивым к сбоям, но, тем не менее, он иллюстрирует некоторые хорошие примеры использования регулярных выражений для совпадения образцов и преобразования строк.
Функция конструктора вместе с методом setWikiData()
просто инициализирует строку примера вводимого текста Wiki следующим образом:
public function WikiParser() { wikiData = setWikiData(); }
Когда пользователь нажимает в демонстрационном приложении кнопку «Проверка», приложение запускает метод parseWikiString()
объекта WikiParser. Этот метод вызывает ряд других методов, которые, в свою очередь, компонуют получившиеся на выводе строки HTML.
Файл Описание
WikiEditor.mxml
или
WikiEditor.fla
Основной файл приложения Flash (FLA) или Flex (MXML).
com/example/programmingas3/regExpExamples/WikiParser.as Класс, включающий методы, которые используют регулярные выражения для преобразования образцов вводимого текста Wiki в эквивалентный выводной текст HTML.
com/example/programmingas3/regExpExamples/URLParser.as Класс, включающий методы, которые используют регулярные выражения для преобразования строк URL в теги гиперссылок <a>
HTML.
com/example/programmingas3/regExpExamples/CurrencyConverter.as Класс, включающий методы, которые используют регулярные выражения для преобразования строк символа доллара США в строки евро.
239
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
public function parseWikiString(wikiString:String):String { var result:String = parseBold(wikiString); result = parseItalic(result); result = linesToParagraphs(result); result = parseBullets(result); return result; }
Каждый из этих вызванных методов — parseBold()
, parseItalic()
, linesToParagraphs()
и parseBullets()
— использует метод replace()
строки с целью замещения совпадающих образцов, определенных регулярным выражением, чтобы преобразовать вводимый текст Wiki в текст формата HTML.
Преобразование образцов полужирного и курсивного шрифтов
Метод parseBold()
производит поиск образца полужирного шрифта Wiki (к примеру, '''foo'''
) и преобразует его в эквивалентный текст HTML (к примеру, <b>foo</b>
) следующим образом:
private function parseBold(input:String):String { var pattern:RegExp = /'''(.*?)'''/g; return input.replace(pattern, "<b>$1</b>"); }
Следует отметить, что часть (.?*)
регулярного выражения соответствует любому числу символов (
*
) между двумя определяющими образцами '''
. Квантификатор ?
делает совпадение непоглощающим с тем, чтобы для строки, такой как '''aaa''' bbb '''ccc'''
, первой совпадающей строкой была '''aaa'''
, а не вся строка (находящаяся внутри образца '''
). Круглые скобки в регулярном выражении определяют группу сбора, а метод replace()
ссылается на эту группу с помощью кода $1 в замещающей строке. Флаг g
(
global
) в регулярном выражении обеспечивает замещение методом replace()
всех совпадений в строке (а не только первого совпадения).
Метод parseItalic()
функционирует практически так же, как и метод parseBold()
, за исключением того, что он проверяет наличие двух (не трех) апострофов (
''
), выполняющих роль ограничителей курсивного текста:
private function parseItalic(input:String):String { var pattern:RegExp = /''(.*?)''/g; return input.replace(pattern, "<i>$1</i>"); }
Преобразование образцов маркера абзаца
Как показывает следующий пример, метод parseBullet()
производит поиск образца строки маркера абзаца Wiki, (к примеру, * foo
) и преобразует его в эквивалентный текст HTML (к примеру, <li>foo</li>
):
private function parseBullets(input:String):String { var pattern:RegExp = /^\*(.*)/gm; return input.replace(pattern, "<li>$1</li>"); }
Символ ^
в начале регулярного выражения соответствует началу строки. Флаг m
(
multiline
) в регулярном выражении является причиной того, что регулярное выражение сопоставляет символ ^
началу линии, а не просто началу строки.
240
ПРОГРАММИРОВАНИЕ НА ACTIONSCRIPT 3.0 В FLASH
Использование регулярных выражений
Образец \*
соо