Я работал с веб-технологиями с конца 90-х, и моей первой серверной технологией был PHP. Позже я занимался разработкой ColdFusion и Java, но всегда считал себя разработчиком PHP. Когда появился AJAX, я начал работать с такими фреймворками, как Prototype и script.aculo.us, и начал создавать свои собственные фреймворки.
В конце 2006 года я впервые попробовал разработку Flex. Это был своего рода ускоренный курс, потому что у меня было около 4-6 недель, чтобы создать демонстрационное приложение для будущей версии FDS (Flex Data Services, теперь называемой LiveCycle Data Services). Хотя я был новичком в Flex и FDS, проект прошел хорошо, и мне действительно понравился процесс разработки и обучения.
Однако, как это ни было приятно, все было иначе. Я имею в виду, что когда я занимался ColdFusion или веб-разработкой на Java, он не чувствовал себя иначе по сравнению с PHP; это был скорее вопрос поиска правильных API и адаптации к специфике языка. Позже, когда я начал делать AJAX поверх DHTML, это тоже не сильно отличалось. Вы по-прежнему создаете большую часть веб-сайта, используя те же приемы с помощью серверного языка, и просто добавляете некоторые специи здесь и там (в данном случае, некоторые виджеты AJAX).
Когда я делал свой первый веб-проект, используя Flex, о, о, боже, это был настоящий поворот! Четкое разделение между клиентом и сервером (бизнес-логика на стороне клиента в дополнение к бизнес-логике на стороне сервера), технология на стороне клиента, которая компилируется вместо интерпретации, два языка на клиенте, все это требует отличное мышление от традиционной веб-разработки.
И это моя причина написания этой статьи. Я хочу поделиться с вами некоторыми вещами, которые специфичны для Flex по отношению к PHP. В то же время я хочу представить Flex, сравнивая его с PHP, когда это сравнение имеет смысл. Таким образом, эта статья предназначена для:
- Разработчики PHP, которые хотят узнать больше о Flex и Action Script 3, чем простое определение, могут предоставить
- Разработчики PHP, которые уже сделали свою первую попытку кодирования приложения Flex и хотят более глубокого и глубокого понимания
Чего нет в этой статье? Я не намерен конвертировать вас или убеждать вас, что Flex лучше, чем X или Y. Я твердо верю, что существуют разные типы проектов, и что они могут и должны выполняться с помощью различных инструментов. А когда производительность, максимальный возврат инвестиций и удобство использования являются главными приоритетами, универсального инструмента не существует.
В то же время, эта статья не полностью документирует Flex или ActionScript 3. Существуют десятки книг, которые освещают эту тему на сотнях страниц. На Flex есть тысячи статей. Мое намерение состоит в том, чтобы дать вам достаточно информации по самым важным темам, и всякий раз, когда имеет смысл связывать концепции с аналогичными концепциями из PHP. Чтобы статья была полезной, я структурировал ее и постарался не вдаваться в подробности. В конце этой статьи я предоставлю краткое введение в Adobe AIR и некоторые дополнительные ресурсы, если вам нужны дополнительные сведения по этой теме.
Наконец, я решил использовать Flex 3 для большинства примеров. Есть несколько причин сделать этот выбор. Во-первых, на момент написания этой статьи Flex 4 все еще находился в стадии бета-тестирования. Во-вторых, Flex 4 — это в основном эволюция Flex 3, поэтому большинство вещей, которые я здесь рассматриваю, могут быть применены к Flex 4 с минимальными изменениями, если таковые имеются. В некоторых случаях я укажу на эти различия. Что касается PHP, я решил использовать PHP 5.3 в качестве ссылки. Сказав это, давайте посмотрим на оглавление, а затем, давайте копаться в!
Что такое Flex?
Самый простой ответ: Flex — это просто еще один способ создания приложения Flash. Приложение Flex скомпилировано в SWF-файл, который проигрывается Flash Player в браузере. Зачем нам нужен другой способ создания Flash-приложений? Традиционно приложения Flash создавались с использованием инструмента разработки Flash. Если вы посмотрите на этот инструмент, вы заметите, что он ориентирован в первую очередь на дизайнеров. Есть сцена, временная шкала, инструменты рисования и так далее.
Когда вы разрабатываете приложения и заботитесь о производительности, вам нужны компоненты, вы хотите иметь возможность максимально упростить разработку за счет повторного использования кода, и не в последнюю очередь, вам нужна современная IDE.
Таким образом, пересмотренный ответ может быть следующим: Flex — это среда с открытым исходным кодом, которая помогает разработчикам быстро создавать многофункциональные интернет-приложения, работающие внутри Flash Player. Фреймворк был в значительной степени сформирован, как и сегодня, в 2006 году, когда появились Flex 2, Flash Player 9 и ActionScript 3. Текущая версия — Flex 3, а в начале 2010 года выйдет следующая версия, Flex 4.
Flex: два языка, одна структура, чтобы связать их
Под зонтиком Flex вы действительно найдете следующее:
- Два языка: MXML и ActionScript 3. Flex предлагает два языка для создания приложения Flex. В следующих главах я углублюсь в каждый язык.
- Богатая библиотека компонентов
- Компиляторы и отладчик
- Инструменты командной строки для компиляции и отладки приложения Flex
Поскольку Flex является средой с открытым исходным кодом, я призываю вас перейти на домашнюю страницу проекта по адресу http://opensource.adobe.com/flex и загрузить SDK. Вы можете увидеть исходный код всех компонентов из библиотеки, проверить открытую базу данных об ошибках и возможностях ( http://bugs.adobe.com/flex ), а также просмотреть вики-страницы со спецификациями.
Частично повышение производительности, обеспечиваемое Flex, связано с обширной библиотекой компонентов. Есть все компоненты пользовательского интерфейса, о которых вы можете подумать (поля ввода, панели, окна, ползунки, сетки данных, поля со списком, аккордеоны, наборы вкладок и т. Д.). Есть макеты контейнеров и элементы формы. Ниже вы можете увидеть скриншот доступных компонентов пользовательского интерфейса из Flex 3 (нажмите, чтобы увеличить).
И если этого недостаточно, поскольку вы можете получить доступ к исходному коду, вы можете расширить их для создания собственных компонентов или создавать новые компоненты с нуля.
Почему вы должны заботиться о Flex
Прежде чем углубляться в то, что такое Flex, давайте остановимся и еще раз рассмотрим причины, по которым вам следует заботиться о Flex.
Традиционные веб-приложения HTML имеют архитектуру запрос-ответ. Браузер делает запрос, и сервер отправляет страницу обратно, и этот цикл повторяется. HTML и CSS — отличный выбор для представления информации, возможно, один из лучших. Прошли годы, однако эта архитектура вышла за пределы просто статического представления платформы приложений. С помощью скриптовых технологий нам удалось создать динамические страницы и адаптировать ответ сервера на конкретный запрос. Кроме того, добавив DHTML и AJAX, мы вдохнули новую жизнь в страницы, обслуживаемые веб-сервером: пользователь мог взаимодействовать с загруженной страницей и изменять вид, не обновляя всю страницу.
По мере развития технологий появлялись более сложные приложения. Некоторые веб-приложения начали дублировать многие функции настольных приложений и в то же время сохранять удобство веб-приложения (доступного везде, где доступны браузер и подключение к Интернету). Таким образом, появились электронные версии электронных таблиц и текстовых редакторов.
Однако с точки зрения удобства использования онлайн-приложения были менее дружественными, чем настольные приложения. В то же время, для создания этих сложных веб-приложений вам понадобится много навыков во многих технологиях (библиотеки JavaScript, DHTML, CSS, AJAX, серверные технологии), а также у вас должен быть опыт работы с различиями между браузерами и тем, как они реализовали HTML / CSS / JS.
Таким образом, в 2002 году Macromedia придумала термин RIA (Rich Internet Applications), чтобы обозначить новое поколение приложений, которые сочетают в себе преимущества веб-приложений и преимущества настольных приложений. Технологией, которая сделала это возможным, был Flash Player.
По сути, если вы хотите создать приложение (не просто веб-сайт или веб-страницу), вы можете сделать это с помощью Flex. Некоторые вещи просто невозможны в HTML / JavaScript, другие очень трудно реализовать согласованно в разных браузерах. Flash Player предлагает один из лучших графических движков, он установлен на 98% компьютеров, подключенных к Интернету, и воспринимает звук и изображения как первоклассных граждан. Он поддерживает микрофоны и веб-камеры, поддерживает потоковую передачу и передачу данных, превосходную поддержку типографики, и этот список можно продолжить.
Взгляните на эти три приложения, чтобы понять, что возможно с помощью Flex:
- SumoPaint бесплатное приложение для редактирования изображений
- Mindomo приложение для составления карт разума
- Times Reader от Нью-Йорк Таймс.
Со временем другие технологии вошли в пространство РИА. Помимо достижений AJAX, которые сделали возможными такие приложения, как Gmail или Google Spreadsheets, сегодня мы видим Silverlight от Microsoft и JavaFX от Sun.
От тонкого клиента до умного / богатого клиента
Давайте вернемся к браузерам и тому, как доставляются веб-приложения. Когда браузер делает запрос, сервер использует комбинацию статического содержимого (код HTML / CSS / JS) и сценариев (эти сценарии могут запрашивать базу данных или вызывать другие сценарии, но в конце они выводят HTML / CSS / JS) для подготовить страницу. Эта страница загружается и отображается браузером. Ключевым элементом здесь является то, что обычно эта страница (или ответ) имеет разметку презентации, а данные запекаются в одно и то же сообщение.
Когда должно быть представлено новое состояние приложения, браузер делает новый запрос, и сервер готовит страницу. Клиент «просто» отображает данные.
Flex приложения работают по-другому. Сервер отправляет скомпилированное приложение Flex (файл SWF), которое запускается внутри браузера с помощью подключаемого модуля Flash Player. Обычно этот SWF-файл содержит только бизнес-логику на стороне клиента. Если нужны данные (например, из базы данных), приложение Flex запрашивает эти данные. Сервер отправляет только данные (это может быть в формате XML, JSON, AMF3), и клиент знает, как визуально представить эти данные. Здесь мы имеем сервис-ориентированную архитектуру: приложение Flex — это клиент-клиент, который может использовать службы данных с сервера. Приложение может изменять состояние без обновления страницы или перезагрузки SWF-файла в браузере. Приложение — это клиент, который может делать больше, чем просто отображать данные.Таким образом, используя Flex и Flash Player, можно создавать практически все, что имеет смысл для развертывания в Интернете, от игр до приложений, виджетов, интегрированных в «классические» веб-приложения, и многое другое.
Но хватит сухой теории, давайте посмотрим код!
Введение в язык MXML
MXML — это декларативный язык на основе XML. В приложении Flex вы используете MXML, чтобы быстро определить структуру / внешний вид вашего приложения. Во Flex все, что вы можете делать с помощью языка MXML, вы можете делать и с ActionScript 3. Однако обратное неверно!
Если вы можете использовать ActionScript 3 для любых действий с MXML, почему MXML существует в первую очередь? Обычно намного проще следовать или понимать пользовательский интерфейс, описанный с использованием языка XML, чем императивный. И это приводит к меньшему количеству кода для пользовательского интерфейса. Также гораздо проще создавать инструменты для декларативных языков, чем для императивных языков. Вот «Привет, мир!» Пример, реализованный с использованием MXML:
1: <Label text="Hello World!" fontSize="14" color="red" x="100" y="50"/>
В этом коде я использую компонент Flex с именем Label для отображения текста на экране. Я установил атрибут текста для текста, который я хочу отображать. Кроме того, я хотел настроить (немного) внешний вид и положение метки на экране. Для этого я использую атрибуты fontSize, color, x и y. Я думаю, вы согласитесь, что это довольно просто понять и следовать.
Теперь рассмотрим тот же пример, реализованный с использованием ActionScript 3:
1: var myLabel = new Label();
2: myLabel.text = "Hello World!";
3: myLabel.setStyle("fontSize", "14");
4: myLabel.setStyle("color", "red");
5: myLabel.x = 100;
6: myLabel.y = 50;
7: addChild(myLabel);
У меня есть семь строк кода, чтобы сделать то, что я сделал в MXML только с одним тегом и некоторыми атрибутами! Теперь представьте, что в реальном приложении у вас есть много элементов управления, сгруппированных в разные контейнеры. Гораздо проще поддерживать код, написанный с использованием MXML, чем код, написанный в виде сотен строк ActionScript 3.
Хотя вы можете использовать MXML для описания своего приложения, вы не можете использовать MXML для реализации бизнес-логики вашего приложения. Для этого вы используете ActionScript 3.
Приложения Flex запускаются в Flash Player, а Flash Player понимает только ActionScript 2 и ActionScript 3. Это означает, что любой код MXML, который вы пишете в приложении, должен быть преобразован компилятором MXML в код ActionScript 3. Этот код преобразуется компилятором ActionScript в байт-код (SWF-файл), который может быть понят Flash Player.
Таким образом, почти за каждым компонентом MXML стоит класс ActionScript 3 (на самом деле есть некоторые теги MXML, у которых нет соответствующего класса ActionScript, например Script и Model ). Например, вот фрагмент из класса Label :
1: public class Label extends UIComponent
2: implements IDataRenderer, IDropInListItemRenderer,
3: IListItemRenderer, IFontContextComponent
4:
5: {
6: /**
7: * Constructor.
8: */
9: public function Label()
10: {
11: super();
12:
13: // this is so the UITextField we contain can be read by a screen-reader
14: tabChildren = true;
15: }
16:
17: /**
18: * @private
19: * Flag that will block default data/listData behavior.
20: */
21: private var textSet:Boolean;
22:
23: ...
24: }
В любом приложении Flex у вас есть хотя бы один файл MXML, который является основным приложением. Например, вот полный код «Hello World!» заявление:
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
3: <mx:Label text="Hello World!" fontSize="14" color="red" x="100" y="50"/>
4: </mx:Application>
Корневой узел всегда должен быть Application , и именно здесь определены пространства имен. В этом случае у меня есть только одно пространство имен для языка MXML и компонентов Flex: mx . (Код выше в Flex 3, во Flex 4 есть небольшие различия в том, что объявлено больше пространств имен).
Если вы пишете свои собственные пользовательские компоненты, вам придется добавить для них пространство имен. Здесь, например, я объявляю второе пространство имен для ссылки на все созданные мной компоненты (в этом примере я использую созданный мной компонент с меткой MyCustomLabel ):
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*">
3: <mx:Label text="Hello"/>
4: <local:MyCustomLabel text="world!"/>
5: </mx:Application>
В этот момент вы можете задаться вопросом, как вы справляетесь с различными страницами приложения Flex. Для веб-сайта HTML различные состояния обычно реализуются на разных страницах. Приложение Flex очень похоже на настольное приложение. Это означает, что вы можете использовать только один файл MXML и отображать на этой странице различные состояния приложения. Flex предлагает для этого несколько способов: от компонентов Flex, таких как Аккордеоны, навигаторы Tabsets, Макет карты, до модулей Flex.
Вы видели, что код MXML можно использовать для определения внешнего вида приложения. Но вы также можете использовать его для создания пользовательских компонентов путем расширения существующих компонентов Flex. Давайте посмотрим на пример. Предположим, у вас в приложении много форм с двумя кнопками: «Сохранить» и «Отмена». Посмотрите на код для этого пользовательского компонента MXML (код создается внутри файла с именем FormButtons.mxml; все файлы MXML должны иметь расширение mxml ):
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="150">
3: <mx:Button id="saveButton" label="Save"/>
4: <mx:Button id="cancelButton" label="Cancel"/>
5: </mx:HBox>
Когда вы создаете пользовательский компонент, вы можете выбрать, какой компонент расширять (вы не можете расширять приложение ). Я решил расширить HBox (горизонтальный блок), который представляет собой контейнер, отображающий все дочерние элементы в одной строке. Внутри контейнера я добавил две кнопки, одну для сохранения и другую для отмены. Я также установил атрибут id для каждого из них. Вы используете значение id как способ ссылки на объект в других частях кода. Это то же самое, что объявить переменную в коде ActionScript.
Теперь давайте посмотрим, как можно использовать этот пользовательский компонент в приложении Flex:
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*" layout="horizontal">
3: <mx:TextInput width="150"/>
4: <local:FormButtons/>
5: </mx:Application>
Ниже вы можете увидеть, как выглядит приложение:
Вы можете подумать, что в MXML вы можете использовать только визуальные компоненты Flex (то есть компоненты, которые в конечном итоге отображаются). На самом деле это не так. У вас могут быть теги MXML, которые представляют данные (объекты, которые используются для хранения данных) или компоненты, которые управляют данными (компоненты, которые могут извлекать / отправлять данные с / на сервер). Ниже вы можете увидеть пример универсального компонента Object, который имеет свойство с именем name :
1: <mx:Object id="myObj" name="Mihai Corlan"/>
Как я уже говорил ранее, все (почти все) компоненты Flex, поставляемые с Flex, имеют класс ActionScript, который реализует внешний вид (если есть) и логику. Когда вы выбираете создание пользовательского компонента (независимо от того, является ли он визуальным компонентом) с использованием ActionScript вместо MXML, вы должны помнить, что существует ограничение: конструктор класса должен иметь возможность вызываться без аргументов ( и если есть аргументы, они должны иметь значения по умолчанию).
Смешивание MXML и ActionScript 3
Возвращаясь к пользовательскому компоненту FormButtons (тот, что с двумя кнопками), вы могли заметить проблему: что если вы хотите использовать этот компонент в месте, где метки Сохранить и Отменить не имеют смысла? Должны ли вы создать другой пользовательский компонент с нужными надписями (скажем, Показать и скрыть )? Конечно, это вариант, но он не масштабируемый и не элегантный! То, что вы действительно хотите, — это более общий компонент и способ изменить компонент с помощью кода. Вот почему рано или поздно вам придется писать код ActionScript в дополнение к коду MXML.
В следующем примере я добавил код ActionScript внутри кода MXML компонента, чтобы определить две переменные, в которых хранятся метки используемых кнопок. Обратите внимание, что я использую новый тег, Script , и внутри него, CDATA . Это связано с тем, что внутри документов XML такие символы, как>, <, &, являются недопустимыми, если они не экранированы. Кроме того, я не буду сейчас уделять много внимания коду ActionScript, но я рассмотрю его более подробно в следующих разделах.
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="150">
3: <mx:Script>
4: <![CDATA[
5: public var label1:String = "Save";
6: public var label2:String = "Delete";
7: ]]>
8: </mx:Script>
9: <mx:Button id="saveButton" label="{label1}"/>
10: <mx:Button id="cancelButton" label="{label2}"/>
11: </mx:HBox>
Переменные, которые я определил, могут быть установлены из приложения Flex, которое использует этот компонент. Итак, давайте посмотрим, как выглядит пересмотренный код приложения Flex при использовании нового пользовательского компонента:
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*" layout="horizontal">
3: <mx:TextInput width="150"/>
4: <local:FormButtons label1="Show" label2="Hide"/>
5: </mx:Application>
Обратите внимание, что в теге FormButtons есть два атрибута: label1 и label2 . Вот как вы можете установить текст, который вы хотите отображать на кнопках. И это механизм, который вы используете, чтобы добавить больше поведения к компоненту MXML (используя код ActionScript). В реальном приложении вы можете привязать поведение к каждой кнопке, чтобы при нажатии кнопки что-то происходило. Вы используете код ActionScript для написания функций, которые будут запускаться нажатием кнопок.
Существует второй способ добавления кода ActionScript в MXML. Вы можете создать файл ActionScript (в этом примере имя файла — buttons.as ) и включить этот файл в файл MXML. Это можно сделать, добавив тег Script с атрибутом источника, который указывает на файл ActionScript. Вот код для этого подхода:
1: // ActionScript file called buttons.as
2: public var label1:String = "Save";
3: public var label2:String = "Delete";
1: <?xml version="1.0" encoding="utf-8"?>
2: <!-- MXML component file called FormButtons.mxml a-->
3: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="150">
4: <mx:Script source="buttons.as"/>
5: <mx:Button id="saveButton" label="{label1}"/>
6: <mx:Button id="cancelButton" label="{label2}"/>
7: </mx:HBox>
Теперь давайте немного отступим назад и разберемся, что происходит, когда компилятор MXML анализирует файл FormButtons.mxml . Вы уже знаете, что весь код будет преобразован в код ActionScript. Но что происходит с существующим кодом ActionScript, который я добавил (две переменные)? Компилятор MXML компилирует каждый файл MXML в класс ActionScript. В этом случае я получу класс FormButtons (потому что это имя файла и он используется для имени класса), который расширяет компонент HBox (потому что я выбрал HBoxв качестве корневого узла компонента). И весь код ActionScript внутри класса становится членами класса: переменные (как в примере) становятся переменными экземпляра, а функции становятся методами экземпляра.
Стили CSS
На этом этапе вам может быть интересно, можете ли вы изменить внешний вид визуальных компонентов Flex. Есть ли что-то вроде CSS для HTML? Ответ — да, Flex поддерживает CSS. Во Flex 4 поддержка CSS расширена, чтобы разрешить определение стилей не только на основе имен классов, но и идентификаторов, чтобы разрешить псевдо-селекторы (например, для кнопки у вас есть селектор вниз, сверх селектор и т. Д.) , и многое другое.
Как и в HTML, стили могут быть определены внутри (внутри кода MXML) или в отдельном файле. Давайте вернемся к пользовательскому компоненту FormButtons и зададим несколько стилей. Если вы решите определить стили в отдельном файле, вы используете тег Style и задаете путь к файлу стиля в атрибуте источника .
1: <?xml version="1.0" encoding="utf-8"?>
2: <!-- MXML component file called FormButtons.mxml a-->
3: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="150">
4: <mx:Style>
5: .Button1 {
6: font-size: 14;
7: color: #990000;
8: }
9: </mx:Style>
10: <mx:Script source="buttons.as"/>
11: <mx:Button id="saveButton" styleName="Button1" label="{label1}"/>
12: <mx:Button id="cancelButton" label="{label2}"/>
13: </mx:HBox>
Я создал CSS-класс с именем Button1, который определяет цвет метки и размер шрифта. Затем я установил стиль для первой кнопки, используя атрибут styleName первой кнопки. Приложение теперь выглядит так:
Стили CSS можно изменить во время выполнения (после загрузки приложения Flex в браузере), и внешний вид приложения немедленно изменится.
Во Flex 4 Adobe добавила новый язык под названием MXML для графики, который добавляет примитивы, эффекты, маски и 2D-преобразования. Вы можете создать класс обложки в файле MXML, используя эти новые теги, а затем вы можете установить этот класс для компонента, который хотите обложить. Ниже вы можете увидеть список обложек во Flex 4. Изображение слева показывает список в состоянии по умолчанию, а справа — состояние наведения. Вы можете увидеть приложение в прямом эфире здесь .
Блуждая в документации по настройке внешнего вида для приложений Flex, вы можете встретить термин «скиннинг». Вы можете сделать графический скин или программный скиннинг, чтобы изменить внешний вид. Вот хорошая статья по этому вопросу.
Изменение кода MXML во время выполнения
Иногда вы хотите изменить компоненты пользовательского интерфейса во время выполнения. Может быть, вы хотите, в зависимости от некоторых данных, которые вы получаете с сервера, создать форму на лету. Опять же, вы можете использовать код ActionScript для этого. Любой визуальный компонент Flex имеет методы для добавления нового дочернего элемента, удаления дочернего элемента, получения всех дочерних элементов и т. Д. Если вы хотите, вы можете сравнить это с тем, как вы меняете DOM в HTML с помощью JavaScript. Однако есть разница: с помощью JavaScript вы можете вводить HTML-код, который можно динамически извлекать с сервера (с помощью вызова AJAX). Во Flex это невозможно, и функция eval () не существует во Flex. Однако есть способ загрузить другие приложения Flex или модули Flex после загрузки основного приложения.
Когда вы знаете , все различные возможными режимы просмотра для компонента, вы можете использовать MXML государство для реализации различных состояний для той же компоненты или приложения. Состояния — это область, в которой Flex 4 значительно улучшил реализацию Flex 3, значительно упростив их использование и добавив больше мощности. В Flex 4 состояния работают так:
- Вы определяете количество состояний и задаете одно по умолчанию
- Затем вы можете указать, в каких состояниях должен отображаться конкретный компонент.
- Вы можете указать отдельные значения для любого атрибута для каждого состояния, в котором он появляется
Предположим, вы хотите создать компонент, который имеет дело с функциями входа в приложение. Вы хотите использовать этот компонент для отображения формы входа в систему, а при успешном входе в систему вы хотите отобразить кнопку выхода из системы и имя пользователя.
Here is how you can create this Login/Logout component using Flex 4:
1: <?xml version="1.0" encoding="utf-8"?>
2: <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo">
3: <s:states>
4: <s:State name="notlogged"/>
5: <s:State name="logged"/>
6: </s:states>
7:
8: <s:TextInput includeIn="notlogged" text="user name"/>
9: <s:TextInput includeIn="notlogged" text="password"/>
10: <s:Button includeIn="notlogged" label="Login" click="{currentState='logged'}"/>
11:
12: <mx:Label includeIn="logged" text="Current user: Mihai Corlan"/>
13: <s:Button includeIn="logged" label="Logout" click="{currentState='notlogged'}"/>
14: <s:layout>
15: <s:HorizontalLayout/>
16: </s:layout>
17: </s:Group>
Код должен быть понятен. В качестве верхнего контейнера я использую компонент Group , для которого макет имеет значение HorizontalLayout (это имеет тот же эффект, что и HBox, использованный в примере Flex 3 выше). Я определил доступные состояния для этого компонента в верхней части файла. Далее у меня есть кнопки, ввод текста и метка. Обратите внимание на атрибуты includeIn, которые указывают, в каком состоянии находится компонент. Просто для записи, есть также атрибут excludeFrom . Если вы хотите иметь кнопку во всех состояниях, то вы ничего не указываете для этих двух атрибутов. Наконец, вы можете видеть, что я назначил выражение для атрибутов щелчка двух кнопок. Например,click = ”{currentState = ‘logged’}» сообщает Flex, что при нажатии кнопки измените состояние компонента на имя с именем logged .
Я включал в эти примеры все больше и больше кода ActionScript, хотя я все еще говорю о языке MXML. Это признак того, что пришло время перейти на второй язык Flex, ActionScript 3.
Введение в язык ActionScript 3
ActionScript 3 — это динамический объектно-ориентированный язык сценариев, который (почти) безопасен для типов. ActionScript 3 основан на спецификациях ECMAScript 3 (ECMA-262). Кроме того, некоторые его функции соответствуют предложению ECMAScript 4. Я обнаружил, что проще всего объяснить ActionScript 3 кому-то, кто является совершенно новым для него таким образом: ActionScript выглядит как смесь JavaScript и Java плюс его имеет свою сильную личность. На самом деле JavaScript — это другой язык, основанный на спецификациях ECMAScript, поэтому вполне естественно иметь что-то общее с ActionScript.
Как я уже говорил, Flash Player может работать с двумя языками: ActionScript 2 и ActionScript 3. Внутренне он использует две разные виртуальные машины, две из которых поддерживают эти два языка (ActionScript 3 и виртуальная машина AVM2 появились в Flash Player 9). ActionScript 3 состоит из основного языка (ключевые слова, типы данных и т. Д.) И API-интерфейса Flash Player (этот API-интерфейс предоставляет разработчикам доступ ко всем функциям Flash Player через API списка отображения, 3D-API, API-интерфейсы рисования, анимации и т. Д. В этой статье я сосредоточусь на основном языке. Вот хорошая вводная статья о ActionScript 3.
Отныне я буду использовать аббревиатуру «AS3» взаимозаменяемо с «ActionScript 3».
Разделительные заявления
В PHP вы используете точку с запятой (;) для разделения или завершения оператора. В AS3 вы можете использовать точку с запятой (;) или просто конец строки. Я должен сказать, что когда я вижу код, написанный без точек с запятой, это не радость для глаз. Итак, я предлагаю вам использовать тот же метод, который вы используете в PHP.
Типы данных, переменные, константы
В PHP есть следующие типы данных: логические, целые числа, числа с плавающей запятой, строки, массивы, объекты, ресурсы и NULL.
В AS3 у нас есть:
- типы данных верхнего уровня: Boolean, int, uint, Number (аналогично плавающей точке из PHP), Strings, Null (содержит только одно значение: null ), void (содержит только одно значение: undefined )
- сложные типы данных: Object, Array, Vector (начиная с Flash Player 10), Dictionary, Bitmap, ByteArray, Date, XML, XMLList, Function, Error, RegExp
В AS3 переменная — это просто идентификатор или ссылка, связанная с фактическим значением. Допустимыми значениями в AS3 являются object ( int или uint — объекты, то же самое относится и к Number или Date ), null и undefined . null и undefined означают отсутствие данных, однако между ними есть разница. Когда вы объявляете переменную и не инициализируете ее, она будет иметь значение null, если тип переменной не Boolean , int , uint или Number, Если переменная не типизирована и не инициализирована, она будет иметь значение undefined . В то же время, когда у вас есть динамический объект, и вы хотите проверить, определен ли определенный метод или свойство, вы можете сравнить его с неопределенным .
В PHP вы объявляете переменную следующим образом:
1: $anInteger = 12;
2: $isTrue = true;
3: $aString = "my string";
4: //or
5: $aString = 'my string';
В AS3 вы используете ключевое слово var при объявлении переменной:
1: var anInteger:int = 12;
2: var isTrue:Boolean = true;
3: var aString:String = "my string";
4: //In AS3 you can not use simple quotes for declaring a String
Обратите внимание, что после имени переменной у меня есть аннотация типа; например, myVarName: Boolean (тип объявляется с использованием « : », за которым следует тип). AS3 позволяет работать с аннотациями типов или без них (если установлен строгий режим для компилятора, вы должны включить аннотации типов).
Исходя из PHP, где вам не нужно объявлять тип переменной, это может показаться странным, и вы можете придерживаться нетипизированного способа действий. Как бы это ни было заманчиво, я настоятельно рекомендую вам использовать аннотации типов. Прежде всего, когда вы используете IDE для написания кода, ввод переменных позволяет вам находить больше ошибок во время компиляции. Например, рассмотрим функцию с одним аргументом String. Если вы попытаетесь вызвать эту функцию, передав объект в качестве аргумента, IDE предупредит вас об этой ошибке.
Без аннотаций типов вы можете получить ошибку во время выполнения, но только тогда, когда вы или конечный пользователь запустите приложение, и в этот момент источник ошибки будет намного труднее определить.
Вторая причина придерживаться аннотаций типов заключается в том, что компилятор AS3 может выполнять оптимизацию, если ему известны конкретные типы переменных.
В PHP вы можете изменить тип переменной с каждым присваиванием:
1: $myVar = 12; //it is an int
2: $myVar = "now is a string";
В AS3 вы можете сделать то же самое (в строгом режиме), только когда вы объявляете переменную без типизации, используя «*»:
1: var myVar:int = 12;
2: //this will raise an error and the application can not be compiled
3: myVar = "this is a string";
4:
5: //declaring the variable untyped you can change the type with each assignment
6: var myVar2:* = 12;
7: myVar2 = "this is a string now";
Вы заметили, что я использую ключевое слово var только при объявлении переменной. Для дальнейших назначений вы опускаете аннотации var и type.
Как я уже говорил, в AS3 переменные — это просто ссылки на реальный объект. Однако, когда вы присваиваете переменную int , uint , Number , Boolean или String другой переменной, создается копия (то же самое происходит при передаче переменной этих типов в функцию). В PHP вы можете использовать оператор «&», чтобы всегда назначать переменные по ссылке, даже для примитивных типов; и когда вы изменяете значение для одной переменной, другая переменная будет указывать на то же самое значение.
Для объединения строк в PHP вы используете «.» (точка), в AS3 вы используете «+» (плюс):
1: //in PHP
2: $space = " ";
3: $a = "this" . $space . "is!";
4:
5: //in AS3
6: var space:String = " ";
7: var a:String = "this" + space + "is!";
В PHP вы можете определять переменные где угодно: на уровне файлов, в функции или в классе. В приложениях Flex переменные могут быть объявлены только внутри функции или на уровне класса.
Кроме того, в PHP вы можете иметь часть процедурного программирования, которая не объявлена внутри функции:
1: <?php
2:
3: $a = 1;
4: for ($i=0; $i<100; $i++) {
5: $a += $i * $a;
6: }
7:
8: ?>
В AS3 вы не можете выполнять операции с переменными вне функций (хотя вы можете объявлять переменные вне функций) с одним исключением, которое я объясню при рассмотрении классов. Таким образом, если вы попытаетесь запустить следующий код, вы получите сообщение об ошибке при компиляции приложения:
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3: <mx:Script>
4: <![CDATA[
5: var a:int = 1;
6: for (var i:int = 0; i<100; i++) { //this raises an error
7: a += i * a;
8: }
9: ]]>
10: </mx:Script>
11: </mx:Application>
Вот как вы можете переписать код для работы:
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
3: <mx:Script>
4: <![CDATA[
5: var a:int = 1;
6:
7: function calculations(a:int):int {
8: for (var i:int = 0; i<100; i++) {
9: a += i * a;
10: }
11: return a;
12: }
13: ]]>
14: </mx:Script>
15: </mx:Application>
В PHP константы объявляются и используются следующим образом:
1: //constants
2: define("CONSTANT", "Hello");
3: $myString = CONSTANT . ‘ world!’;
В AS3 константы объявляются с использованием ключевого слова const (существует соглашение именовать константы заглавными буквами):
1: static const HELLO:String = "Hello";
2: var myString:String = HELLO + " world!";
Что можно использовать в качестве имени переменной? Здесь PHP и AS3 похожи: до тех пор, пока первый символ имени представляет собой букву или «_», за которыми следуют буквы, цифры или подчеркивание, это допустимо. Вот примеры имен переменных, которые допустимы на обоих языках: _1, _a1A, b.
В PHP у вас есть способ использовать переменную, зная ее строковое имя:
1: <?php
2: $myVar = 12;
3: $varName = 'myVar';
4: echo($$varName); //print 12;
5: ?>
Вы можете добиться аналогичной функциональности в AS3, используя динамический метод ссылки на члены (переменные / методы).
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
3: <mx:Script>
4: <![CDATA[
5:
6: var myVar:int = 12;
7:
8: function init():void {
9: var varName:String = "myVar";
10: trace(this[varName]); //output 12
11: }
12: ]]>
13: </mx:Script>
14:
15: </mx:Application>
В примере я использовал это для ссылки на текущий объект, но вы можете использовать ту же технику для любого объекта. Я добавлю больше об этом, когда буду говорить о динамических классах.
Функции и анонимные функции (замыкания)
В AS3 вы можете делать все с помощью функций, которые вы можете выполнять в PHP, и некоторые другие.
Во-первых, в AS3 вы можете определить тип аргументов и тип возвращаемого значения (в PHP вы можете добавлять аннотации типов только к методам из объектов).
1: function calculate(x:int=0, y:int=0):int {
2: return x + y;
3: }
4: //using the function
5: var result:int = calculate(1, 2);
6:
7: function calculateAverage(...arguments):Number {
8: var result:Number = 0;
9: for (var i:int=0; i<arguments.length; i++) {
10: result += arguments[i];
11: }
12: return result/arguments.length;
13: }
14:
15: //using the function
16: var result:Number = calculateAverage(1, 2, 3, 4, 5, 6);
Вы можете смешивать оператор… (rest) с явными аргументами, если вы поместите оператор rest как последний в списке аргументов: function foo (x: int, y: int,… arguments): Number {} . Оператор rest может быть полезен, когда вы хотите создать функции с переменным числом аргументов.
Если функция ничего не возвращает, вы используете void в качестве типа возврата.
В PHP и AS3 вы можете иметь значения по умолчанию для аргументов. Например:
1: //php code
2:
3: function doThing($a, $b="default value") {
4: echo $a . $b;
5: }
6:
7: //AS code
8: function doThing(a:String, b:String="default value"):void {
9: trace(a + b);
10: }
Конечно, вы можете определить функции внутри функции (вы увидите пример в следующем примере кода).
Во-вторых, в AS3 любая функция представлена как экземпляр класса Function . Это делает возможным некоторые интересные вещи:
- Вы можете создать буквальную функцию и назначить ее переменной, а затем вызвать функцию через эту переменную (это также возможно в PHP)
- вы можете вернуть функцию в результате выполнения другой функции
- Вы можете передавать функции в качестве аргументов при вызове других функций
1: var f:Function = function multiply(x:int, y:int):int {
2: return x*y;
3: }
4:
5: trace(f(3,5));
6:
7: function giveMeAFunction():Function {
8: return function multiply(x:int, y:int):int {
9: return x*y;
10: };
11: }
12:
13: var h:Function = giveMeAFunction();
14: trace(h(3,4));
В PHP и AS3 вы можете создавать анонимные функции (или замыкания). В предыдущем примере кода вы можете увидеть пример создания анонимной функции внутри giveMeAFunction () и ее возврата.
Возможно, самая большая разница между функциями в AS3 и PHP заключается в том, как вы их определяете. В PHP вы можете определить любое количество функций в файле. В AS3 вы можете определить только одну функцию в файле, и имя функции должно совпадать с именем файла. Например, если вы определяете функцию с именем doSomeMath () , вы должны создать эту функцию в файле с именем doSomeMath.as . При определении функций вы используете объявления пакетов (вы узнаете о пакетах в следующем разделе). Таким образом, если вы хотите создать набор служебных функций, если вы не хотите записывать их в набор файлов, вы можете создать один класс и определить их как статические методы.
ООП: классы и интерфейсы
Настало время перейти к объектно-ориентированному программированию в PHP и AS3. В PHP вы можете написать объектно-ориентированный или процедурный код; AS3 является объектно-ориентированным.
Давайте начнем с простого класса PHP, чтобы увидеть различия в синтаксисе (помните, я использую PHP 5.3 в качестве ссылки):
1: namespace org\corlan {
2:
3: class SimpleClass {
4:
5: public $public = 'Public';
6: protected $protected = 'Protected';
7: private $private = 'Private';
8:
9: function SimpleClass() {
10:
11: }
12: // Redefine the parent method
13: function displayVar()
14: {
15:
16: }
17: }
18: }
19:
20: //use the class like this
21: require_once('flassFile.php');
22: $obj = new org\corlan\SimpleClass();
23: $obj->displayVar();
В AS3 тот же класс записывается следующим образом:
1: package org.corlan {
2:
3: public class SimpleClass {
4:
5: public var _public:String = "Public";
6: protected var _protected:String = "Protected";
7: private var _private:String = "Private";
8:
9: function SimpleClass() {
10:
11: }
12:
13: // Redefine the parent method
14: public function displayVar():void
15: {
16:
17: }
18: }
19:
20: }
21:
22: //you use the class like this:
23: import org.corlan.SimpleClass;
24:
25: var object:SimpleClass = new SimpleClass();
26: object.displayVar();
Вот основные отличия:
- называя файл, в котором хранится класс
- В PHP вы можете определить класс в файле, который может быть назван в любом случае
- В AS3 имя файла должно совпадать с именем класса (если класс называется SimpleClass , тогда файл должен быть SimpleClass.as )
- пространства имен против пакетов
- В PHP вы можете использовать пространства имен, чтобы избежать конфликтов имен между классами
- В AS3 вы используете пакеты; однако, когда вы объявляете класс, который находится, например, в пакете org.corlan, это означает, что класс будет находиться внутри папки org / corlan в исходной папке Flex. Имя пакета переводится в структуру папок. Пакеты, используемые вместе с модификаторами доступа к классам, могут скрывать классы за пределами проекта (подробнее об этом позже)
- требуют / включают против импорта
- В PHP обычно вы включаете файл, в котором класс определяется с помощью функции require_once. Начиная с PHP 5, вы можете определить функцию __autoload () и выполнить в этой функции require_once или include_once вместо того, чтобы писать список необходимых файлов в верхней части каждого файла.
- В AS3 вы используете оператор импорта для включения нужного класса. Однако, если вы хотите включить все классы из пакета org.corlan, вы можете написать импорт, используя подстановочный знак: import org.corlan. *. Другое отличие состоит в том, что компилятор AS3 будет компилировать только те классы, которые фактически используются в вашем коде (то есть только тогда, когда фактически создается экземпляр этого конкретного класса).
- вызов метода / члена в экземпляре:
- В PHP вы используете оператор «->»
- В AS3 вы используете «.» (точка) оператор
Теперь перейдем к модификаторам класса / методов / членов.
Я начну с модификаторов классов:
- PHP имеет окончательный и абстрактный ; public неявный, все классы являются публичными в PHP
- AS3 имеет общедоступный , внутренний , окончательный и динамический характер . Если вы не укажете никакой модификатор доступа ( публичный или внутренний ), то класс по умолчанию является внутренним, то есть доступ к нему могут получить только классы из одного и того же пакета. public и final имеют то же значение, что и в PHP; абстрактный не существует в AS3, но вы можете преодолеть это ограничение, используя интерфейсы. Динамически помечает класс как класс, который можно изменить во время выполнения путем изменения существующих членов или добавления новых.
Модификаторы для свойств класса:
- PHP имеет: публичный , приватный , защищенный , статический
- AS3 имеет модификаторы PHP плюс внутренний . Внутренний используется для того, чтобы сделать свойства доступными только внутри одного пакета. Когда модификатор не указан, используется internal .
Модификаторы для методов класса:
- PHP имеет публичный , приватный , защищенный , статический , финальный и абстрактный .
- AS3 имеет: открытый , закрытый , защищенный , статический , окончательный , внутренний и переопределенный . Аннотация не существует в AS3; internal делает методы доступными только для кода из одного пакета.
В AS3 все, что вы можете сделать с закрытием функции, вы можете сделать с помощью методов класса.
Конструкторы в PHP могут быть помечены как частные, вы можете определить конструктор с тем же именем, что и имя класса, или вы можете использовать специальные методы __construct (), __destruct (). В AS3 конструктор всегда общедоступен и должен иметь то же имя, что и имя класса. Если ничего не предоставлено, AS3 создаст один за кулисами для вас.
Доступ к статическим членам или статическим методам:
- В PHP используется ClassName :: propertyName
- В AS3 используется ClassName.propertyName . Однако внутри одного и того же класса вы можете оставить имя класса.
1: package org.corlan {
2:
3: public class Foo {
4:
5: private static myVar:String;
6:
7: function Foo() {
8: Foo.myVar = "value 1";
9: myVar = "value 2";
10: }
11:
12: }
13: }
это :
- В PHP вы используете специальную переменную класса $ this для ссылки на члены класса (переменные / методы), определенные в одном и том же классе: $ this-> myVar = 22;
- В AS3 используется тот же это : this.myVar = 22; однако, вы можете отказаться от этого и просто использовать myVar = 22 .
В AS3 только один класс может быть объявлен внутри пакета (этот класс дает имя файла). Однако вне объявления пакета вы можете объявить столько классов, сколько пожелаете:
1: package org.corlan {
2:
3: public class Foo {
4:
5: private static var instance:Foo;
6:
7: function Foo(object:Bar) {
8:
9: }
10:
11: static public getInstance():Foo {
12: if (Foo.instance == null) {
13: Foo.instance = new Foo(new Bar());
14: }
15: return Foo.instance;
16: }
17:
18: }
19:
20: class Bar {}
Это имеет интересный эффект: все классы, определенные в файле вне пакета, будут доступны только для кода, объявленного внутри того же файла. Для всего остального кода их не существует. Помните ограничение, что в AS3 вы не можете объявить конструктор закрытым? Что ж, используя технику, аналогичную этому примеру, вы можете убедиться, что существует только один экземпляр класса Foo . Если какой-то внешний код вызывает конструктор, будет сгенерировано исключение времени выполнения, поскольку внешний код не может использовать экземпляр Bar, поскольку этот класс невидим для внешнего кода.
наследование
Расширение классов в AS3 очень похоже на то, как это делается в PHP. Вы используете то же ключевое слово extends, за которым следует имя класса, который вы хотите расширить. Переопределение такое же, как в PHP, с той лишь разницей, что вы должны добавить ключевое слово override к сигнатуре метода. Перегрузка не поддерживается (у вас не может быть двух или более методов с одинаковым именем).
В PHP вы получаете доступ к родительским элементам, используя синтаксис parent :: memberName ; в AS3 вы используете super.memberName . Когда конструктор класса выполняется, сначала вызывается родительский конструктор. Это происходит, даже если вы не вызываете это явно из своего кода. Таким образом, когда у вас есть код в методе конструктора, вы не можете вызывать родительский конструктор после вашего кода. Таким образом, вы даете возможность правильно инициализировать родительский класс, чтобы ребенок не использовал элементы, которые еще не установлены. Вы вызываете родительский конструктор, используя этот синтаксис: super () . Давайте посмотрим, как работают эти концепции: сначала код PHP, а затем код AS3.
1: class SimpleClass {
2:
3: function SimpleClass() {
4: echo('SimpleClass() called');
5: }
6:
7: function __construct() {
8:
9: }
10:
11:
12: function displayVar()
13: {
14: echo "SimpleClass class\n";
15: }
16: }
17:
18: class ExtendClass extends SimpleClass {
19:
20: function ExtendClass() {
21: $myVar = 1;
22: parent::SimpleClass();
23: //or
24: parent::__construct();
25: }
26: // Redefine the parent method
27: function displayVar()
28: {
29: echo "Extending class\n";
30: parent::displayVar();
31: }
32: }
1: public class SimpleClass {
2:
3: function SimpleClass() {
4: trace("SimpleClass() called");
5: }
6:
7: public function displayVar():void
8: {
9: trace("SimpleClass class");
10: }
11: }
12:
13: public class ExtendClass extends SimpleClass {
14:
15: function ExtendClass() {
16: super(); //we have to call first the parent constructor, and only after we can execute our code
17: var myVar:int = 1;
18: }
19:
20: override public function displayVar():void {
21: trace("overrided displayVar()");
22: super.displayVar();
23: }
24: }
Давайте посмотрим, как класс инициализируется в AS3. Когда создается экземпляр класса, сначала инициализируются все свойства, затем выполняется статический код, определенный на уровне класса (это невозможно в PHP), и затем выполняется конструктор. Вот пример:
1: public class Foo {
2:
3: private var a:int = 0;
4: private static var os:String;
5: trace("initializer");
6:
7: if (Capabilities.os == "LINUX")
8: os = "LINUX";
9: else
10: os = "other";
11:
12: public function Foo(a:int=1) {
13: trace("foo() executed");
14: }
15: }
16:
17: var foo1:Foo = new Foo();
18: var foo2:Foo = new Foo();
19: //produces this output in console:
20: initializer
21: foo() executed
22: foo() executed
В AS3 вы можете создавать объекты из замыканий функций, используя свойство prototype функции (это похоже на то, что вы используете в JavaScript для создания / расширения классов). Вот краткий пример:
1: //we create a function
2: function MyClass(value:String = "Mihai") {
3: //we create a property
4: this.name = value;
5: }
6: //we use the special variable prototype of the function
7: //to create another method
8: MyClass.prototype.setName = function (value:String):void {
9: //we have access to the property defined on MyClass object
10: trace(this.name);
11: this.name = value;
12: trace(this.name);
13: }
14:
15: //create an instance
16: var myObject = new MyClass();
17: //accesing the method created earlier
18: myObject.setName("Joe");
Я расскажу больше о динамических особенностях AS3 в следующем разделе.
Геттеры / сеттеры
В любом языке ООП вы обычно используете методы получения / установки для управления свойствами класса, которые вы хотите выставить снаружи. PHP не является исключением. Однако в AS3 есть специальная поддержка свойств с использованием ключевых слов set и get . Вот пример:
1: public class Employee {
2:
3: private var _salary:int = 0;
4: private var _income:int = 0;
5:
6: function Employee() {
7:
8: }
9:
10: public function set salary(value:int):void {
11: if (value > 0) {
12: this._salary = value;
13: this._income = this._salary * 12;
14: }
15: }
16:
17: public function get salary():int {
18: return this._salary;
19: }
20:
21: public function get income():int {
22: return this.income;
23: }
24: }
25:
26: //using this class
27: var emp:Employee = new Employee();
28: emp.salary = 1000;
29: trace(emp.income);
30: //this raise an error, because the income property is read-only
31: //for the outside code
32: emp.income = 120;
По сути, хотя у меня есть setter и getter для поля _salary , я могу вызывать эти методы, как если бы они были полями или свойствами, а не функциями: object.salary = 20 вместо object.salary (20) . И если вы решите не определять сеттер, вы получите свойства только для чтения. Это то, что я сделал со свойством _income .
Эта функция, помимо того, что делает код немного чище, облегчает написание API или классов, которые будут использоваться другими. Предположим, что в моем примере я решил создать поле _salary в качестве открытого члена. Если позже я решу, что мне нужно проверить значения, которые можно установить, я должен добавить установщик. В PHP это будет что-то вроде myObject.setSalary () . В этот самый момент любой код, который использует класс, не работает; это должно быть обновлено, чтобы использовать сеттер.
В AS3 вы можете запустить класс со свойством, определенным как public var salary: int, и когда вы решите, что вам нужен установщик, вы переименуете переменную и добавите метод set salary () публичной функции . Любой код, который использует класс, не подвержен этому изменению, поскольку он все еще обращается к свойству, используя тот же синтаксис: objectInstance.salary = 10 .
В AS3 существует соглашение об использовании этого стиля сеттеров и геттеров для добавления подчеркивания к имени переменной.
Интерфейсы
Интерфейсы работают почти одинаково в PHP и AS3. Заметным отличием является то, что, хотя в PHP вы можете определять методы и константы, в AS3 вы можете определять только методы. Однако вы можете определить сеттеры / геттеры:
1: public interface IEmployee {
2:
3: public function set salary(value:int);
4: public function get salary():int;
5: public function get income():int;
6: }
Исключения
Как и в PHP, AS3 имеет поддержку исключений:
1: try {
2:
3: } catch(e:Error) {
4:
5: } finally {
6:
7: }
8:
9: //throwing an exception
10: throw new Error("Some error");
Ошибка является верхним классом для всех ошибок в AS3. Вы можете создавать свои собственные ошибки, расширяющие этот класс, или вы можете использовать существующие подклассы.
Приведение и тестирование типа объекта
Иногда вы хотите привести объект к другому типу или проверить тип. Для проверки типа в PHP вы используете instanceof , в AS3 вы используете is . Чтобы выполнить приведение, в AS3 у вас есть два разных синтаксиса.
1: class A {};
2:
3: class B extends A {};
4:
5: var b:A = new B();
6: //casting
7: var c:B = b as B;
8: //or
9: var d:B = B(b);
10:
11: //checking the type of an variable
12: if (b is A)
13: trace(true);
14: if (b is B)
15: trace(true);
Переменная область
Посмотрев, как переменные, функции и классы работают во Flex и AS 3, пришло время поговорить о области видимости переменных. В PHP в основном у вас есть две области: глобальные (переменные, определенные на уровне файлов) и локальные (переменные, определенные внутри функций).
Во Flex есть пять возможных областей действия: тело функции, тело метода экземпляра, тело статического метода, тело класса и глобальная область действия. Добавление к ним модификаторов доступа (публичный / приватный / защищенный / внутренний) делает вещи немного сложнее, чем в PHP.
Области могут быть вложенными; в этом случае переменные / функции / члены охватывающей области становятся доступными для вложенной области. Например, когда вы объявляете анонимную функцию внутри тела другой функции, в AS3 все переменные, определенные во внешней функции, доступны внутри вложенной функции. В PHP вы должны передать переменные, которые вы хотите использовать, или добавить оператор использования :
1: //php code
2: function a() {
3: $a = 1;
4: $b = 2;
5:
6: function b() use ($a, $b) {
7:
8: }
9: }
10:
11: //AS3 code
12: function a():void {
13: var a:int = 1;
14: var b:int = 2;
15:
16: function b():void {
17: //variables a and b are available here
18: }
19: }
Когда вы объявляете функцию внутри неназванного пакета, она помещается в глобальную область видимости и становится доступной для всего кода. Однако все, что объявлено вне пакета, все еще находится в глобальной области видимости, но оно видно только для кода из того же файла.
Массивы
Массивы в AS3 очень похожи на массивы из PHP, с одним отличием: в AS3 массив может иметь только числовые индексы. Если вы хотите создать ассоциативный массив, вы можете использовать класс Object . Если вы хотите создать хеш-карту, где ключи являются объектами (а не строками), вы можете использовать класс Dictionary . Вы создаете массив, используя класс Array , и вы можете иметь многомерные массивы. И для Object, и для Array вы можете использовать буквальное определение. Давайте посмотрим несколько примеров:
1: var myArray1:Array = new Array(1, 2, "some string");
2: //creates an array with three elements: 0->1, 1->2, 3->some string
3:
4: //literal definition for an array
5: var myArray2:Array = [1, 2, 3];
6: //ading two more elements
7: myArray2.push(4,5);
8:
9: //a hash map, similar to associative arrays in PHP
10: var myMap:Object = new Object();
11: myMap.name = "Flex";
12: //literal definition of a map
13: var myMap2:Object = {name:"Flex"};
14:
15: //using Dictionary class
16: var dic:Dictionary = new Dictionary();
17: var anObject:Object = new Object(); //creating the key
18: dic[anObject] = "some value"; //adding a value to Dictionary
У вас есть все ожидаемые методы для добавления или удаления элементов, включая push , shift , pop , unshift и splice . Concat может использоваться для добавления массивов в другой массив. В предыдущем примере вы можете увидеть, как я использую push, чтобы добавить еще два элемента в массив.
Массивы не фиксированной длины; они могут расти, когда вы добавляете больше элементов. В PHP вы используете «[]», чтобы добавить новый элемент в конец массива. В AS3 есть аналогичный метод, который использует свойство длины массива (вы также можете использовать свойство длины, чтобы уменьшить размер массива):
1: var array:Array = new Array();
2: array[array.length] = 1;//array has the values: 1
3: array[array.length] = 23;//array has the values: 1, 23
Вы можете использовать delete, чтобы установить для определенного элемента массива значение undefined: delete array [index] . Это не сократит длину массива. Вы можете использовать оператор for () для обхода массива, используя его свойство length . Если вы хотите перебрать объект Object (опять же, это можно использовать для создания чего-то похожего на PHP ассоциативные массивы), вы можете использовать операторы for — each (который работает аналогично той же конструкции в PHP) или for — (подробнее об этом в динамическом разделе).
Пространства имен
Если вы ищете эквивалентную концепцию AS3 для пространств имен PHP, вам следует прочитать о пакетах в разделе «Классы», поскольку пакеты AS3 похожи на пространства имен PHP.
В ActionScript пространство имен имеет другое значение. Давайте посмотрим, для чего используются пространства имен, а затем приведу несколько примеров:
- предотвращение конфликтов имен (вы можете создать несколько методов с одним и тем же именем в одном классе, каждый в своем пространстве имен)
- помечать переменные и методы в рамках фреймворков / программ настраиваемым параметром видимости (например, Flex использует пространство имен с именем mx_internal ; использование пространства имен вместо частного или защищенного позволяет использовать эти методы в любом пакете и классе из среды Flex. В то же время разработчики предупреждаются, что эти методы или члены не предназначены для внешнего использования, поскольку они могут измениться)
- реализовать управление доступом на основе разрешений для класса
- создать класс, который может переключать свое поведение на основе определенного выбранного пространства имен
Прежде чем углубляться в детали, я должен отметить, что пространства имен используются Flash Player для реализации модификаторов доступа: общедоступных , защищенных , внутренних и частных .
Вы определяете пространство имен, используя этот синтаксис: идентификатор пространства имен = URI. Идентификатор — это то, что вы будете использовать при объявлении переменных / методов и когда вы хотите квалифицировать элемент или метод для его использования. URI обычно является URL-адресом, который должен быть уникальным для вашего приложения. Он не должен существовать, и в большинстве случаев вы бы использовали свое доменное имя. Например, я бы определил пространство имен следующим образом: namespace online = «http://corlan.org/apps/online» .
Вы можете определить пространство имен везде, где могут быть определены переменные: на верхнем уровне определения пакета (оно будет доступно для всей программы) или на уровне класса (оно будет доступно только в том классе, в котором оно определено). На уровне функций вы можете использовать только пространство имен, которое было определено где-то еще (это может понадобиться для определения переменной, которая была определена где-то еще, с использованием того же пространства имен; для этого вам нужно знать URI).
Вы можете объявить метод или переменную в заданном пространстве имен, поместив идентификатор пространства имен перед объявлением. Например: mynamespace var a: int = 1 . Когда вы определяете переменную или метод в пространстве имен, вам не разрешается использовать другие модификаторы доступа (например, private).
Чтобы вызвать переменную или метод, который был определен в пространстве имен, вы используете оператор квалификатора имени « :: ». Предположим, что вы определили метод myMethod () в пространстве имен онлайн , вы можете получить доступ к методу, используя следующий синтаксис: objectInstance.online::myMethod () . То же самое касается переменных. Иногда вам может понадобиться использовать много переменных или методов, которые должны быть квалифицированы по имени пространства имен. Вы можете открыть пространство имен в этой области и избавиться от оператора квалификатора имени. Это делается с помощью директивы use namespace namespaceidentifier . Например:
1: public function doSomething() {
2: use namespace online;
3: //call the method defined in that namespace:
4: myMethod();
5: }
Вы можете передавать пространства имен, например, вы можете возвращать пространство имен из метода, позволяя вызывающему коду использовать его для определения метода или члена.
Теперь давайте создадим два пространства имен, которые можно использовать для изменения поведения класса во время выполнения. Сначала я определю два пространства имен (я буду использовать один файл для каждого пространства имен):
1: // ActionScript file online.as
2: package org.corlan {
3: public namespace online = "http://corlan.org/apps/online";
4: }
1: // ActionScript file offline.as
2: package org.corlan {
3: public namespace offline = "http://corlan.org/apps/offline";
4: }
Далее я буду использовать эти два пространства имен для создания класса, который сохраняет объект. В зависимости от состояния подключения он может сохранять объект локально (например, с помощью локального хранилища) или удаленно на сервере (с помощью службы REST). Интересная часть возникает, когда некоторый код должен использовать этот класс. Вызывающий код не заботится о методе вообще; он просто хочет сохранить объекты.
Используя эти два пространства имен, я создам класс, который имеет два метода с именем save (), каждый из которых определен в одном из двух пространств имен. Далее у меня есть приватная переменная, которая хранит текущее пространство имен, которое будет использоваться в зависимости от состояния интернет-соединения. Вызывающая программа обращается к текущему пространству имен с помощью метода get и использует его для вызова метода save () . Опять же, вызывающая программа не знает обо всех этих внутренних объектах и не знает ни о пространствах имен, ни об этом. Давайте посмотрим код PersistObject :
1: package org.corlan {
2: import flash.events.Event;
3:
4: public class PersistObject {
5:
6: private var _mode:Namespace = offline;
7:
8: public function PersistObject() {
9:
10: }
11:
12: online function save(object:Object):void {
13: //save the object back to server
14: trace("online");
15: }
16:
17: offline function save(object:Object):void {
18: //save the object locally
19: trace("offline");
20: }
21:
22: private function connectivityChanged(e:Event):void {
23: //here the mode can be changed from offline to online
24: //and vice-versa
25: }
26:
27: public function get mode():Namespace {
28: return this._mode;
29: }
30: }
31: }
Следующий фрагмент кода использует этот класс. Код прост, и встроенные комментарии должны объяснить это.
1: //creating an object that we want to be stored
2: var object:Object = {book:"Ulysses", author:"James Joyce"};
3: //create an instance of PersitObject
4: var persistenceObject:PersistObject = new PersistObject();
5: //get the current namespace
6: var currentMode:Namespace = persistenceObject.mode;
7: //use the namespace we retrieved to qualify the save method()
8: persistenceObject.currentMode::save(object);
Доступность пространства имен
Вы можете использовать те же самые модификаторы доступа, которые вы используете для переменных или методов: публичные , внутренние , защищенные и частные (для пространств имен, определенных на уровне пакета, вы можете использовать только публичные и внутренние ). Комбинируя это с расположением определения пространства имен, вы получаете большой контроль над видимостью пространства имен в программе.
Работа с XML
В PHP существует обширная поддержка XML с помощью собственных функций или дополнительных расширений. В AS3 есть два класса, которые изначально представляют XML: XML и XMLList . AS3 реализует класс XML на основе W3C DOM (у вас есть такие методы, как children () , appendChild () , parent () , insertChildBefore () и т. Д.). При работе с XML полезно знать, как использовать E4X. E4X (ECMAScript-for-XML) — это расширение языка ECMA-262, которое реализовано в AS3. Вы используете XML для представления документа XML. Любой узел из документа помещается в список XMLList, даже если есть только один дочерний элемент.
Вы можете создать объект XML, используя любой из следующих методов:
- написать XML, используя буквальную форму
- создать экземпляр XML, а затем импортировать XML из внешнего файла
- создайте экземпляр XML и используйте точечную нотацию для добавления / изменения структуры:
1: var author:XML = <author/>;
2: author.@id = 1; //setting an attribute called id and its value
3: //adding two child nodes to author:
4: author.name = "Mihai Corlan";
5: author.article = "Flex for PHP developers";
6:
7: //this code is equivalent with:
8: var author:XML = <author id="1">
9: <name>Mihai Corlan</name>
10: <article>Flex for PHP developers</article>
11: </author>;
Используя E4X, вы можете легко находить узлы, создавая условия на основе имени узлов или значений атрибутов. Вы можете использовать оператор-потомок «..», чтобы получить все узлы с заданным именем (например, чтобы получить все программные узлы, которые вы можете написать: Programs..Program ). Вы можете создавать условия на основе атрибутов, используя оператор «@» (например, Programs..Program. (@ Id == 2) ). И, наконец, используя точечную запись, вы можете перемещаться по узлам (просто имейте в виду, что любой дочерний элемент рассматривается как XMLList, даже если он является единственным дочерним элементом). Ниже вы можете увидеть примеры использования E4X для работы с XML.
1: var programs:XML = <root>
2: <program id="1">
3: <name>Flex</name>
4: </program>
5: <program id="2">
6: <name>ActionScript 3</name>
7: </program>
8: <program id="3">
9: <name>AJAX</name>
10: </program>
11: </root>;
12:
13: //retrieving the second program node and printing its name
14: trace(programs.program[2].name[0]);
15: //retrieving all the program nodes:
16: var list:XMLList = programs..program;
17: //retrieving all the program nodes that have an id attribute equal to 2
18: var list:XMLList = pograms..program.(@id==2);
Динамический ActionScript
Помните определение AS3? В определении я указал, что AS3 является динамическим языком сценариев. Давайте углубимся в эту функцию. Динамический означает, что объект может быть изменен во время выполнения путем добавления или удаления методов или членов. Можно добавить новые методы в сам класс (и любой объект, созданный из этого класса, будет иметь эти методы). Вы даже можете создавать новые классы с нуля (используя свойство protoype ). В AS3 есть встроенные динамические объекты, такие как Object , а во Flex есть еще один пример, ObjectProxy .
Если вам интересно, почему эта функция существует в первую очередь, ответ прост: более ранние версии ActionScript не имели всех функций и ООП, которые AS3 предлагает сегодня. Я должен сказать, что из моего опыта, не многие разработчики используют динамические функции AS3. Есть несколько причин для этого. Первое время доступа для динамических элементов медленнее, чем для фиксированных. Во-вторых, вы получите код, более подверженный ошибкам (например, нет проверки ошибок во время компиляции).
Вы не ограничены встроенными классами; Вы можете создавать динамические объекты, используя динамический модификатор в определении класса:
1: dynamic public MyDynamicObject {
2:
3: }
Теперь, используя только что определенный класс yoy, вы можете добавлять члены во время выполнения (помните, что все динамические переменные экземпляра не типизированы и общедоступны):
1: var a:MyDynamicObject = new MyDynamicObject();
2: a.author = "Mihai Corlan";
Вы можете циклически проходить через все члены динамического класса, используя цикл for-each-in . Вот как вы можете отобразить элементы из предыдущего примера:
1: for each (var element:* in a) {
2: trace(element); //displays Mihai Corlan
3: }
Если вы хотите получить имена членов вместо их значений, вы используете цикл for-in :
1: for (var memberName:* in a) {
2: trace(memberName); //outputs author
3: trace(a[memberName]); //outputs Mihai Corlan
4: }
Flex асинхронный
До сих пор я рассмотрел многие функции Flex, и многие из них были очень похожи на их аналоги в PHP. Однако асинхронная природа Flex отличается от всего, что есть в PHP. Важно понять это, прекратить бороться с этим и плыть по течению.
Что это значит, что Flex асинхронный? Предположим, вы создали приложение Flex, и после загрузки приложения в браузере пользователь может выбрать загрузку изображений с другого сайта. Вы можете использовать класс URLLoader для этой задачи. Когда вы выполняете метод load () , на следующей строке кода у вас не будет данных. Скрипт не останавливается после загрузки ()вызов в ожидании загрузки данных. Вместо этого выполнение сценария возобновляется. Как программист, вы имеете дело с этой асинхронной природой, используя встроенную систему событий AS3. Если вы знакомы с программированием AJAX, это похоже на то, что вы делаете, когда делаете вызов AJAX: вы предоставляете функцию обратного вызова, а когда данные поступают, вызывается функция обратного вызова, и вы можете получить доступ к загруженным данным.
Возвращаясь к примеру ULRLoader , вы бы добавили прослушиватель событий для результирующего события. Это функция, которая будет вызываться после загрузки данных. Вот пример того, как может выглядеть код:
1: function loadPic():void {
2: var loader:URLLoader = new URLLoader();
3: loader.dataFormat = URLLoaderDataFormat.BINARY;
4: //adding the event handlers or listeners
5: loader.addEventListener(EventComplete, picLoaded);
6: loader.addEventListener(IOErrorEvent.ID_ERROR, picError);
7: //starting the loading
8: loader.load(new URLRequest("http://some_url"));
9: }
10:
11: //event handler for
12: function picLoaded(event:Event):void {
13: //get the data from the loader object
14: //use the target property to get the loader object
15: (event.target as URLLoader).data;
16: }
17:
18: //event handler for the error event
19: function picError(event:IOErrorEvent):void {
20: //displays the error id in a pop-up windonw
21: Alert.show(event.errorID);
22: }
Я могу подвести итог так: не звоните нам, мы вам позвоним!
Как я уже сказал, AS3 имеет встроенную систему событий. Верхний класс всех событий — Событие . Все объекты, которые работают асинхронно, имеют метод addEventListner () , и первые два аргумента являются типом события и именем функции, которая вызывается при возникновении события. Вы можете подумать, что только объекты, которые имеют дело с извлечением удаленных данных, подчиняются этой модели событий. На самом деле это не так; все визуальные компоненты или объекты также имеют события. Например, каждое приложение Flex имеет событие creationComplete . Это событие запускается, когда все необходимые компоненты из приложения обрабатываются и отображаются на экране.
Хотя вам может показаться, что такой код не так прост, как PHP, есть веская причина разбросать асинхронные вызовы во Flex (и Flash Player): Flex — это технология на стороне клиента. Если бы все вызовы были синхронными, пользовательский интерфейс приложения перестал бы отвечать на любые вызовы, например, связанные с загрузкой данных. И пользователи ненавидят неотзывчивые пользовательские интерфейсы.
Вы можете отменить некоторые события и даже изменить поведение по умолчанию. Я дам вам изучить эти детали самостоятельно, если вам нужно; сейчас у вас должно быть достаточно хорошее представление о том, что такое события и слушатели событий.
Привязка данных, теги метаданных и отражение
Привязка данных — это еще одна функция Flex, которая значительно облегчает жизнь разработчику и в то же время уменьшает количество строк кода. Привязка данных — это элегантный способ связать модель данных с представлением и автоматически обновить представление, чтобы отразить любое изменение модели данных.
Поскольку Flex используется для создания пользовательских интерфейсов приложений, компоненты Flex обычно отображают большое количество данных. Когда данные изменяются, даже в режиме реального времени, вы обычно хотите отображать самые последние данные, а не старые. Используя привязку данных, вы можете достичь этого очень легко. Привязка данных связывает свойство объекта (называемое источником) со свойством другого объекта (называемого назначением), поэтому при каждом изменении источника назначение автоматически обновляется.
Во Flex 4 есть поддержка двунаправленной привязки (на самом деле вы можете сделать это и во Flex 3, но вам нужно объявить это на втором шаге), что означает, что она работает и наоборот: когда пункт назначения обновляется, новое значение копируется в источник. Это полезно, когда у вас есть модель данных и форма. Вы связываете модель данных с формой, и когда пользователь изменяет значения в форме, двунаправленное связывание данных обновляет модель данных значениями формы. Пришло время увидеть код.
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal">
3: <mx:Script>
4: <![CDATA[
5:
6: [Bindable]
7: private var labelValue:String = "Hello World!";
8:
9: private function add():void {
10: labelValue += "!";
11: }
12: ]]>
13: </mx:Script>
14: <mx:Label id="myLabel" text="{labelValue}"/>
15: <mx:Button label="Add a !" click="add()"/>
16: </mx:Application>
Bindable метаданных на labelValue переменных помечает его как источник привязки данных. Затем я использовал « {} » для атрибута текста метки, чтобы пометить это свойство как место назначения привязки. Имея привязку на месте, каждый раз, когда изменяется переменная labelValue , метка обновляет свое представление, чтобы отразить это изменение. Я мог бы использовать одну и ту же переменную для многих надписей или текстовых входов, и все они были бы обновлены, чтобы отразить новое значение.
Существует также синтаксис MXML: <mx: Binding source = ”labelValue” destination = ”myLabel.text” /> .
Если вы хотите привязать данные к редактируемому элементу управления (например, к текстовому вводу) и скопировать значение обратно в источник, во Flex 4 вы можете выполнить двунаправленную привязку с помощью оператора « @ »:
1: <s:TextInput id="txt" text="@{labelValue}"/>
И если вы хотите использовать тег Binding , установите для атрибута twoWay значение true (опять же, это возможно только в Flex 4):
1: <mx:Binding source="labelValue" destination="myTextBox.text" twoWay="true"/>
Чтобы реализовать привязку данных, Flex добавляет клейкий код во время компиляции (помните, что привязка данных не является функцией Flash Player или AS3), и прелесть в том, что вам не нужно писать этот код самостоятельно.
Хотя привязка данных предлагает простой способ привязки модели данных к представлению, производительность будет снижена, если у вас будет набор привязок для переменных, которые обновляются десятки или сотни раз в секунду. Для таких переменных нет необходимости часто обновлять пользовательский интерфейс, поскольку существует ограничение на количество кадров в секунду, устанавливаемое самим браузером (где-то около 50 кадров в секунду). В результате бессмысленно пытаться отображать сотни изменений в секунду в режиме реального времени.
Следует также помнить, что не все объекты являются связываемыми. Например, Object и Array не могут быть привязаны, вы должны использовать ObjectProxie и ArrayCollection, Когда вы создаете классы для моделирования данных, если вы хотите, чтобы все члены класса были привязываемыми, вы можете поместить метаданные Bindable на уровне класса вместо добавления для каждого свойства:
1: package org.corlan {
2:
3: [Bindable]
4: public class VOAuthor {
5:
6: public var id_aut:int;
7: public var fname_aut:String;
8: public var lname_aut:String;
9: }
10: }
Теперь перейдем к тегам метаданных (иногда их называют аннотациями). Вы уже видели теги метаданных в виде тега метаданных Bindable . Чтобы получить полный список тегов метаданных, которые вы можете использовать с Flex, нажмите здесь . В некоторых случаях теги метаданных используются компилятором MXML для генерации связующего кода (как в случае с Bindable ), в других случаях вы можете использовать теги метаданных, чтобы дать подсказку IDE Flash Builder или создать свойства в тег MXML. Это случай метаданных события . Например, предположим, я пишу класс, который генерирует событие при загрузке фильма. Я могу использовать тег метаданных события, чтобы объявить тип события и имя. Таким образом я могу использовать movieLoadedEventсвойство тега MovieLoader MXML, чтобы зарегистрировать прослушиватель событий для этого события. Давайте посмотрим код класса и как вы можете использовать класс в MXML.
1: //class definition
2: package org.corlan {
3: import flash.events.EventDispatcher;
4: import flash.events.IEventDispatcher;
5:
6: [Event(name="movieLoadedEvent", type="flash.events.Event")]
7:
8: public class MovieLoader extends EventDispatcher {
9:
10: public function MovieLoader(target:IEventDispatcher=null) {
11: super(target);
12: }
13:
14: }
15: }
1: <?xml version="1.0" encoding="utf-8"?>
2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
3: xmlns:local="org.corlan.*" layout="horizontal">
4: <mx:Script>
5: <![CDATA[
6: private function movieLoadedListener(event:Event):void {
7: //do something with it
8: }
9: ]]>
10: </mx:Script>
11:
12: <local:MovieLoader id="loader" movieLoadedEvent="movieLoadedListener(event)"/>
13: </mx:Application>
There are other interesting things you can do with metadata. If you set a flag on the compiler (keep-as3-metadata followed by the tag’s names), you can add your custom metadata tags and the compiler will put the tags in the bytecode. You can then use these tags at runtime. For example, in this post, you can read how you use custom metadata tags to provide a way to persist a given data model in an AIR application (more about Adobe AIR a little bit later).
And this brings me to the last topic of this section: reflection. In order to use the custom metadata you have to rely on the AS3 reflection API.
In PHP there is a complete object-oriented reflection API: Reflection, ReflectionFunction, ReflectionParameter, ReflectionMethod, and so on. Here is an example using the Reflection class on a simple PHP class:
1: class SimpleClass {
2:
3: public $public = 'Public';
4: protected $protected = 'Protected';
5: private $private = 'Private';
6:
7: private function SimpleClass() {
8: echo('SimpleClass() called');
9: }
10:
11: private function __construct() {
12:
13: }
14:
15: function displayVar() {
16: echo "SimpleClass class\n";
17: }
18: }
19:
20:
21: Reflection::export(new ReflectionClass('SimpleClass')); //this outputs:
22:
23: Class [ <user> class SimpleClass ] {
24: @@ /Applications/MAMP/htdocs/_learning/classes.php 7-26
25:
26: - Constants [0] {
27: }
28:
29: - Static properties [0] {
30: }
31:
32: - Static methods [0] {
33: }
34:
35: - Properties [3] {
36: Property [ <default> public $public ]
37: Property [ <default> protected $protected ]
38: Property [ <default> private $private ]
39: }
40:
41: - Methods [3] {
42: Method [ <user> private method SimpleClass ] {
43: @@ /Applications/MAMP/htdocs/_learning/classes.php 13 - 15
44: }
45:
46: Method [ <user, ctor> private method __construct ] {
47: @@ /Applications/MAMP/htdocs/_learning/classes.php 17 - 19
48: }
49:
50: Method [ <user> public method displayVar ] {
51: @@ /Applications/MAMP/htdocs/_learning/classes.php 22 - 25
52: }
53: }
54: }
55:
AS3 there are three functions in the flash.utils package that can be used for reflection: describeType(), getDefintionByNameI(), and getQualifiedSuperClassName(). Here is an example of the output of describeType() (the output is an XML object):
1: public class SimpleClass {
2:
3: public var _public:String = "Public";
4: protected var _protected:String = "Protected";
5: private var _private:String = "Private";
6:
7: function SimpleClass() {
8: trace("SimpleClass() called");
9: }
10:
11: public function displayVar():void
12: {
13: trace("SimpleClass class");
14: }
15: }
16:
17: function reflect():void {
18: var s:SimpleClass = new SimpleClass();
19: var description:XML = describeType(s);
20: trace(description);
21: }
22:
23: //the output:
24: <type name="org.corlan::SimpleClass" base="Object" isDynamic="false" isFinal="false" isStatic="false">
25: <extendsClass type="Object"/>
26: <method name="displayVar" declaredBy="org.corlan::SimpleClass" returnType="void"/>
27: <variable name="_public" type="String"/>
28: </type>
Where are my data? Bring it on!
As a PHP developer, you have a very direct way to read data, parse them, and display them on the screen. Connecting to a MySQL database is one of the first things any PHP developer learns. In fact, I highly doubt that you managed to read this whole article to this point without peeking at this section.
What about Flex? I have to disappoint you, because you don’t have direct access to data stored in a database. But there is something good in this, I guess, because you can continue to write PHP files to read/write data to your database, even when writing Flex applications . Why is there no direct way of reading data from a database? Because of the old saying “You should never trust the client!” Suppose the client is a Flex component that knows how to connect to the MySQL server. How do you store the credentials so that it wouldn’t be easy to steal them and have the database compromised? Set a different user/password for each user and give them this information? This is just one of the reasons why it is not a good idea to have a client technology that can connect directly to a database server, without using an application server in the middle.
Basically, in Flex applications you rely on server-side scripts to manage the databases. Flex offers you a way to call the server pages and get back the answer in Flex. There are three different ways to connect to a server data source: REST style services, web services, and Remoting (or RPC).
You can use the HTTPService class to use REST style services. You can send POST variables when you do a request, and the response can be XML, JSON (there is a third-party library for parsing JSON), or custom formatting.
If you have web services on the server (SOAP/WSDL), you can use the WebService class.
But the most interesting method is remoting (using the RemoteObject class). There are three reasons why I think is the coolest method. First, using remoting you can leverage any PHP class you have on your server by calling any public method. Basically, from the Flex side you use an instance of RemoteObject as if it were the remote PHP class. Second, you can map the data model from the PHP side to an ActionScript data model, and have the conversion done automatically. This is extremely important, because when you use typed objects, you get the benefits of compile-time error checks and code completion. This means code that is easier to read and less prone to bugs. And third, the messaging format for this method, AMF3 (Action Message Format) is a binary format, which can be much faster and smaller compared to SOAP/XML/JSON, especially for big sets of data. The format itself is open, and anyone can read the white papers and implement programs that use it.
AMF3 быстрее, потому что он кодирует данные. Например, если одна и та же строка повторяется в наборе данных, то она кодируется один раз, а все остальные вхождения строки являются ссылками. Если число меньше четырех битов, то используется только минимальное количество требуемых байтов.
Джеймс Уорд из Adobe создал хороший
тест, который показывает различия между удаленным взаимодействием и другими методами.
Remoting is natively supported by Flex, however on the server side the story is not the same. PHP doesn’t support remoting and AMF3 natively. This is why you need a server side library to enable remoting for a PHP web server. There are four available libraries, all are free, and I wrote tutorials about how to use each of them: Zend AMF, PHPAMF, WebORB for PHP, SabreAMF. And here you can read a post that compares them.
Because native data type are converted automatically (PHP type to a AS3 type and vice-versa), you have to pay attention how the native types from one language are converted to the other. Here is an example for the correspondence of data types in the AMFPHP library.
User authentication in Flex and PHP projects
So how can user authentication be done in Flex and PHP projects? The answer is very simple, just as with PHP websites, you use a session and some way to validate the user/password.
Basically whenever a call is done from Flex, the session id is automatically appended. Thus, if the user was previously authenticated, the same session will be used.
More on this subject here.
Working on Flex and PHP projects
Fortunately, both PHP and Flex are mature technologies, thus and you have plenty of choices when it comes to tools. I will present some of them in this section.
Flex SDK and text editors
The first option you might consider is to use the free open source Flex SDK, especially if you love command-line tools and text editors like vi . You can write the code in your favorite text editor, and use the command-line tools to compile/debug the application.
Flex Builder / Flash Builder and Eclipse PDT / Zend Studio
I prefer to use a modern IDE. For Flex and PHP projects, probably the best combination is Flex Builder or Flash Builder 4 and Zend Studio. Flex Builder is the name of the Adobe’s Flex IDE up to the fourth version; the fourth version was renamed to Flash Builder 4. This IDE is Eclipse based, it is available for Windows and Mac OS, and it come as a plug-in version and a standalone version. For example if you have Zend Studio, you might consider the Flash Builder plug-in, and install this plug-in on top of Zend Studio. You can use Flex Builder 3 for 60 days (trial version), and Flash Builder 4 is in beta now (summer of 2009). If you are a teacher or student you can get a license for free.
If you prefer to work with Eclipse PDT, you can use the same approach: install the plug-in version of Flash Builder 4 or the other way around, install PDT on top of the Flash Builder standalone.
Flash Builder 4 offers wizards for working with PHP and Flex: it can introspect PHP code and generate AS3 and Flex code (here is tutorial on this matter). You can use it to debug, profile, compile, and launch the application (web or AIR). You can also export the application for release, and there is support for refactoring as well as a Design view and a states editor.
It also integrates with Flash Catalyst, so you can create the UI of the application in Flash Catalyst and then open the generated project in Flash Builder 4 and continue adding the business logic (you can watch this screen cast to see how you can create a vertical scrollbar using Adobe Illustrator, Flash Catalyst, and Flash Builder 4).
There are other IDEs (commercial products) for Flex: IntelliJ IDEA and FDT (Eclipse Based).
Debugging Flex applications
You can debug Flex code using the debugger from the Flex SDK, or the debugger from Flash Builder 4 (or Flex Builder 3). If you chose a combined set-up of Flash Builder 4 and Zend Studio, then you can debug the PHP and Flex code from the same project very easily. You make a call from Flex to PHP and you can enter the PHP debugger, then when the answer is back in Flex, and you enter the Flex debugger. Here and here are some videos on this topic, and here is a tutorial on Zend Studio and Flex Builder debugging.
In PHP one of the first approach I try when I have bugs is to use a combination of die() and var_dump() calls to see what is happening. In AS3 you can use trace() to output variables values to console. The cool thing is that when you compile the application for production, all the trace() statements are removed. This is an un-obstructively way to output information; you can also use Alert class to display messages in a pop-up window (more like JavaScript debugging before having FireBug).
The key element to keep in mind is: now, you have a client that it is separated from the server, and problems may be on the client, on the server, or at the network level.
You can read more on debugging Flex and PHP projects here.
What is Adobe AIR
Adobe AIR is a desktop runtime for RIAs that run as desktop applications on Windows, Mac, and Linux. With AIR, you can create a single application that can run on any of these operating systems. Examples of AIR applications: Tour de Flex, TweetDeck, Times Reader, Dojo Toolbox, and Sideline from Yahoo!.
You might think of Adobe AIR as a “Flash Player” for the desktop. However, Adobe AIR is more than just a modified Flash Player.
Inside of this runtime, there is an HTML engine (WebKit, the same engine used by Safari and Google Chrome) and a modified Flash Player engine. These two engines offer a set of APIs that give access to the machine on which an AIR application runs. There are APIs for writing/reading files on the disk, detecting network connectivity, detecting the number of connected displays and resolution, application updates, desktop notifications, local databases, drag and drop, and more.
As a web developer you can choose any combination of the following technologies: Flex, ActionScript 3, or HTML/CSS/JavaScript. That’s right; you can create an AIR application using only HTML, JavaScript, and CSS. Actually, the Dojo Toolbox and Sideline from Yahoo! are created using HTML/CSS/JS.
So with AIR you can leverage your existing skills to build a desktop application. But why would you want to create a web application that runs as a desktop app? Actually there are many reasons for this:
- you want to be able to use the application, or parts of it, when you don’t have an Internet connection
- you want to get rid of the browser chrome, and to fully customize the appearance of your application
- you want to be able to integrate the application with other applications on the user’s computer (for example, to drag and drop files from the AIR app to desktop and vice-versa)
- you want to be able to persist files on the user’s machine
- you want to build a notification system, and you want to run the application minimized in system tray (for example, instant messengers can notify you when a new message is received, although they are minimized and not having the focus)
For developing AIR applications, you can use the free AIR SDK (you have command line tools for building, testing, and debugging), you can use Aptana Studio (if you want to create AIR apps using HTML/JS/CSS), or you can use Flash Builder 4 (or Flex Builder 3).
Finally, any Flex application that was created for the browser can be transformed into an AIR application in no time. Of course, if you stop here and you don’t make use of the specific AIR features, it doesn’t make sense because you haven’t provided any additional value.
What’s next?
Early next year Flex 4 will be released. Adobe has developed a new tool (it is still in beta) called Flash Catalyst that can be used to transform static designs created in Photoshop or Illustrator into functional Flex user interfaces. Imagine a tool that could take as input a Photoshop or Illustrator file, and output HTML/CSS/JavaScript code and retaining the look and feel of the input files. This is what Flash Catalyst is doing, only it outputs Flex 4 code and not HTML.
At the same time, we are focusing heavily on making the Flash Platform available on all screens: from computers to mobiles devices, from set-top boxes to TV sets. Now we have Flash Lite 3 available on mobiles (Nokia, Sony Ericsson, HTC, Android, Palm). Next year, we’ll release the mobile version of Flash Player 10. Also, it is very possible that next year we’ll see the first TV sets with support for Flash. How cool would it be to have user interface that takes advantage of all the Flash Player features, or to be able to watch high definition videos from the web (Flash has support for the H-264 standard). Some analysts think that in the near future there will be more mobile phones connected to the Internet than computers, and many people will use their mobile devices as the primary means for accessing Internet content as they will not have a computer.
What does this mean for a web developer? It means that you can expand your area of expertise and what you offer from web sites to desktop RIAs (using Adobe AIR), and from computers to mobiles and other devices with screens. Of course, in order to do that, you need to brush up some of your skills, but the level of complexity is not even close to what it takes to become proficient with C or C++ for a given platform.
Where to go from here
I hope you found answers to some of your questions. If you are serious about entering the Flex world, here are some resources:
Tour de Flex
I view Tour de Flex as the Web 2.0 or RIA version of the beloved php_manual.chm. You can install it from here. It provides examples of how to use any component in Flex (you can see how it looks and the code used to implement it). There is also easy access to the Flex documentation. The application itself is created using Flex and Adobe AIR.
Books
There are many books on Flex and ActionScript 3. However my personal favorites, and those I usually recommend are these:
- First steps in Flex, by Bruce Eckel and James Ward (Technical Evangelist at Adobe); this book gives you an overview of how you can use Flex for developing web and desktop applications, and you can read it in one weekend.
- Essential ActionScript 3 by Colin Moock; this is a thick book, and you have to be an excellent reader to cover the book in one weekend. Although it doesn’t cover Flex, you can learn almost everything about ActionScript 3.
Websites
There are hundreds of websites and blogs covering Flex and ActionScript 3. It would be impossible to give you the complete list, but I will give you some of my favorites:
- Adobe Developer Connection. A great place to read technical articles about Flash, Flex, and AIR. It is updated weekly. There is a section dedicated to Flex and PHP.
- Adobe TV. This site gives you access to tons of videos with presentations from conferences and video tutorials.
- Gotoandlearn.com. An excellent collection of video tutorials by fellow evangelist Lee Brimelow.
- Flex documentation. Keep in mind that you can download a ZIP file of this documentation. You can find here resources in various formats.
- Adobe Groups. A free platform where you can find Adobe User Groups (including Flex or Flash groups). Have a look, there might be a Flex User Group in your area, and usually they organize meetings monthly. There are forums under this platform, and they support localization, so there is content not only in English.
- My blogroll. Check it out; most of them are people from Adobe who write about Flash and Flex.
- Have a look at the list I maintain on frameworks, libraries, and other Flex-related resources.
And now, I think, you can understand why when a developer asks me what Flex is, I stare blankly for a while. During this time, all the thousands of words I wrote here pass in front of my eyes…there is so much to talk about, what the heck could I possibly say in one line!? Hopefully, now I can just answer “Flex is awesome, dude! Check this article. ”.
If you have comments, please take your time to leave one on this page. Thanks!