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

Однако если нельзя использовать модификаторы управления доступом, с помощью чего можно управлять доступностью уточненного идентификатора? Ответ: с помощью доступности идентификатора уточняющего пространства имен.

Видимость уточненных идентификаторов

373

^ I Доступность уточняющего пространства имен в уточненном идентификаторе определя-

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

Например, в выражении game items. fruit: : orange переменная fruit: : orange доступна тогда, и только тогда, когда пространство имен fruit доступно в области видимости этого выражения. Доступность переменной fruit: : orange целиком и полностью определяется доступностью пространства имен fruit.

В листинге 17.2 демонстрируется видимость уточненного идентификатора на примере обобщенного кода.

Листинг 17.2. Демонстрация видимости уточненного идентификатора

// Создаем пространство имен п в пакете one. видимое только в этом пакете package one { internal namespace n = «http://www. example. eom/n»;

// Создаем переменную n::p в классе А, пакет one package one { public class A { n var p:int = 1:

// Поскольку пространство имен n объявлено с использованием модификатора // управления доступом internal, переменная п::р доступна в любом месте // внутри пакета one package one { public class В { public function В ( ) { var a:A = new A( ); trace(a. n::p); // OK

// Однако переменная n::p недоступна для кода за пределами пакета one package two { import one.*;

public class С { public function С ( ) { var a:A = new A( );

trace(a. n::p); // Недопустимо, поскольку пространство имен n

// объявлено с использованием модификатора управления // доступом internal в пакете one. и поэтому // недоступно в пакете two

Сравнение уточненных идентификаторов

Два пространства имен считаются одинаковыми тогда, и только тогда, когда совпадают их названия (URI). Например, чтобы определить, являются ли одинаковыми пространства имен в уточненных идентификаторах fruit : : orange и color: : orange, среда выполнения Flash не проверяет, соответствуют ли буквы слова «fruit» первого идентификатора буквам слова color второго идентификатора. Вместо этого среда Flash проверяет, совпадают ли значения переменной ur i экземпляра класса Namespace, на который ссылается идентификатор fruit, и экземпляра класса Namespace, на который ссылается идентификатор color. Если значение переменной f ruit. uri равняется значению переменной color, uri, то пространства имен считаются одинаковыми.

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

Таким образом, когда мы записываем следующее выражение:

trace(fruit::orange == color::orange);

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

{http://www. examplе. com/games/ki dsgame/fruit}orange == {http://www. example. com/games/ki dsgame/col or}orange

Даже если два уточненных идентификатора внешне кажутся различными, на деле они могут оказаться одинаковыми и привести к неожиданным конфликтам имен. Например, в следующем коде попытка определить переменную ns2 : : р вызовет ошибку на этапе компиляции, поскольку переменная с расширенным именем {http : / /www. example. com/general}p уже существует:

namespace nsl = «http://www. example. com/general»

namespace ns2 = «http://www. example. com/general»

nsl var p:int = 1:

ns2 var print = 2; // Ошибка! Повторное определение переменной!

Даже несмотря на то, что идентификаторы ns 1 и ns 2 являются различными, переменные nsl: :р и ns2: : р считаются одинаковыми, поскольку они имеют одинаковые расширенные имена ({http: / /www. example. com/general }p).

Стоит отметить, что названия пространств имен (идентификаторы URI) сравниваются как строки, с учетом регистра символов. Поэтому, несмотря на то, что для браузера два идентификатора URI, которые отличаются только регистром символов, будут считаться одинаковыми, в языке ActionScript они будут считаться различными. В ActionScript следующие два идентификатора URI считаются различными, поскольку слово example в первом случае начинается со строчной буквы, а во втором — с прописной:

namespace nsl = «http://www. example. com» namespace ns2 = «http://www. Example. com» trace(nsl == ns2); // Отображает: false

Присваивание и передача значений пространств имен

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

? передавать пространство имен из одной области видимости в другую;

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

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

При использовании пространств имен в ActionScript эти действия являются крайне важными. Узнаем почему.

Присваивание значения пространства имен переменной

Чтобы присвоить значение пространства имен переменной, мы используем точно такой же синтаксис присваивания, как и для любого другого значения. Например, следующий код присваивает значение пространства имен fruit переменной currentltemType (напомним, что значение пространства имен — это объект класса Namespace):

// Файл fruit. as package {

namespace fruit = «http://www. example. com/games/kidsgame/fruit»;

}

// Файл Items. as package { public class Items {

// Присваиваем значение пространства имен fruit переменной

// currentltemType

private var currentltemType-.Namespace = fruit;

}

}

Переменная, которая ссылается на объект класса Namespace, может быть использована для формирования уточненного идентификатора. Например, рассмотрим следующее определение переменной:

fruit var orange:String = «Round citrus fruit»;

Для того чтобы обратиться к этой переменной, мы можем использовать выражение fruit: : orange либо currentltemType: : orange. Присвоив переменной currentltemType некоторое другое пространство имен, можно динамически изменить смысл идентификатора currentltemType: -.orange, а также всех остальных методов и переменных, уточняемых переменной currentltemType по всей программе. Если организовать группы методов и переменных с помощью пространств имен, мы можем воспользоваться возможностью динамического

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

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

Например, предположим, что мы создаем приложение для мгновенного обмена сообщениями, которое может функционировать в двух режимах, представляемых соответствующими пространствами имен offline и online. В приложении определены две версии метода с именем sendMes sage ( ): одна версия предназначена для работы в режиме онлайн, а другая — для работы в автономном режиме.

online sendMessage (msg.-String):void { // Отправить сообщение прямо сейчас…

}

offline sendMessage (msg.-String):void { // Поставить сообщение в очередь и отправить его позднее…

}

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

private function connectListener (e:Event):void { currentMode = online;

}

private function closeListener (e:Event):void { currentMode = offline;

}

Во всех обращениях к методу sendMessage ( ) в качестве уточняющего пространства имен применяется переменная currentMode, как показано в следующем коде:

currentMode::sendMessage(«yo dude»);

Изменяя значение переменной currentMode, приложение динамически переключается между двумя версиями метода sendMessage ( ) в зависимости от состояния соединения.

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

Далее, в подразд. «Пример: реализация режимов работы программы» разд. «Практические примеры использования пространств имен», мы вернемся к концепции использования пространств имен в качестве режимов работы программы на примере японско-английского словаря, в котором происходит переключение между различными режимами поиска.

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

namespace fruit;

var currentltemType:Namespace = fruit;

currentltemType var orange:String = «Round citrus fruit»;

вызовет такую ошибку:

Namespace was not found or is not a compile-time constant.

По-русски это будет звучать так: Пространство имен не найдено, или оно не является константой на этапе компиляции.

Аналогичным образом переменные не могут быть использованы для указания пространства имен в директиве use namespace. Мы познакомимся с этой директивой далее, в разд. «Открытые пространства имен и директива use namespace».

Пространства имен в качестве аргументов и возвращаемых значений методов

Вдобавок к тому, что значения пространств имен могут присваиваться переменным и элементам массива, они могут передаваться в методы и возвращаться из них. Например, следующий код определяет метод doSomething ( ), который принимает значение пространства имен в качестве аргумента:

public function doSomething (n:Namespace):void { trace(n);

}

Этот код передает пространство имен fruit в метод doSomething ( ): doSomething(fruit):

Пространство имен может передаваться в метод для того, чтобы перенести одну часть контекста программы в другую. Например, приложение, реализующее корзину в интернет-магазине, может передавать пространство имен currentLocale в класс Checkout, который затем динамически выберет подходящую валюту и зависящее от времени приветствие, взяв за основу текущее местоположение пользователя.

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

Этот код определяет метод getNamespace ( ), который возвращает пространство имен fruit:

public function getNamespace ( ):Namespace { return fruit:

}

Пространство имен может возвращаться из метода для того, чтобы предоставить вызывающему коду привилегированный доступ к закрытым переменным и методам. Полный пример, демонстрирующий возврат пространства имен из метода в качестве части системы управления доступом на основе разрешений, можно найти далее, в подразд. «Пример: управление доступом на основании разрешений» разд. «Практические примеры использования пространств имен».

Пример использования значения пространства имен

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

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

Бегло просмотрите код в листинге 17.3, чтобы получить общее представление о программе. В данном примере пространства имен используются только в классах I terns и Kids Game, поэтому вы должны сосредоточить свое внимание на этих классах. Информацию о методиках, применяемых для создания пользовательского интерфейса в этом примере, можно найти в части П. Подробный анализ кода представлен сразу после листинга.

Листинг 17.3. Детская игра: пример использования значения пространства имен

// Файл fruit. as package {

public namespace fruit = «http://www. example. com/games/kidsgame/fruit»;

}

// Файл color. as package {

public namespace color = «http://www. example. com/games/kidsgame/color»;

}

// Файл Items. as package {

‘ // Простой класс для хранения данных, содержащий объекты Item для игры, public class Items { // Фрукты

fruit var orange:Item = new Item(«Orange», «fruit-orange. jpg», 1); fruit var apple:Item = new ItemC’Apple», «fruit-apple. jpg», 2);

// Цвета

color-var orange-.Item = new Item( «Orange», «color-orange. jpg», 3); color var purple:Item = new ItemCPurple», «color-purple. jpg», 4);

// Массивы, хранящие полные наборы элементов (то есть все фрукты // или все цвета)

fruit var itemSet:Array = [fruit::orange, fruit::apple]; color var itemSet:Array = [color::orange, color::purple];

// Массив пространств имен, представляющих

// типы наборов элементов в игре

private var itemTypes:Array = [color, fruit];

// Возвращает все элементы-фрукты, используемые в игре fruit function getltems ( ):Array { return fruit::itemSet. slice(0);

}

// Возвращает все элементы-цвета, используемые в игре color function getltems ( ):Array {

return color::itemSet. siice(O);

}

// Возвращает список доступных типов элементов, используемых в игре public function getltemTypes ( ):Аггау { return i temTypes. s1i се(0);

}

}

// Файл KidsGame. as package {

import flash. display.*;

import flash. events.*;

import flash. utils.*;

// Основной класс приложения для детской игры «Учусь читать», которое // демонстрирует основы использования пространств имен в языке ActionScript. // Игроку показывается картинка с цветом или фруктом и предлагается выбрать // название этого цвета или фрукта из списка вариантов, public class KidsGame extends Sprite { private var gameltems:Items; // Список всех элементов, используемых

// в игре

private var thisQuestionltem:Item; // Элемент для каждого вопроса private var questionScreen:QuestionScreen; // Пользовательский интерфейс

// Конструктор

public function KidsGame( ) { // Получаем элементы, используемые в игре (фрукты и цвета, // названия которых должен указать игрок) gameltems = new Items( ); // Отображаем первый вопрос newQuestion( );

}

// Создаем и отображаем новый случайный вопрос public function newQuestion ( ):void {

// Получаем полный список типов элементов (массив пространств имен)

var itemTypes:Array = gameltems. getItemTypes( );

// Случайным образом выбираем тип элемента (одно из пространств имен,

// на которые ссылается переменная itemTypes)

var randomltemType:Namespace = itemTypes[Math. floor(

Math. random( )*itemTypes.1ength)];

// Получаем элементы набора, выбранного случайным образом var items:Array = gameltems. randomltemType: -.getItems( );

// Случайным образом выбираем элемент для данного вопроса // из набора элементов

thisQuestionltem = iterns[Math. floor(Math. random( )*iterns. length)];

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

Глава 17. Пространства имен

// Удаляем предыдущий вопрос, если он существует if (questionScreen!= null) { removeChild(questionScreen);

}

// Отображаем новый вопрос

questionScreen = new QuestionScreen(this, items, thisQuestionltem); addChild(questionScreen);

}

// Обрабатываем ответ игрока public function submitGuess (guess:int) .-void { traceCGuess: » + guess + «, Correct: » + thisQuestionltem. id); if (guess == thisQuestionltem. id) { questi onScreen. di splayResult(«Correct!»); // Отключить кнопки ответа до тех пор, пока игрок не дождется // следующего вопроса. questionScreen. disable( );

// Подождать 3 секунды перед отображением следующего вопроса, var timer:Timer = new Timer(3000, 1); timer. addEventLi stener(TimerEvent. TIMER, doneResultDelay); timer. start( ); } else {

questionScreen. di spl ayResultC Incorrect. Please try again.»);

}

}

// Создает новый вопрос после того, как был получен // ответ на предыдущий.

private function doneResultDelay (e:TimerEvent):void {

newQuestion( ); } ‘

}

// Файл Item. as package {

// Простой контейнер данных, который хранит информацию об элементе, public class Item {

// Название элемента (например, «apple»)

public var name:String;

// Адрес URL, с которого загружается изображение, // представляющее элемент public var src:String;

// Уникальный идентификатор элемента, который используется // для обработки ответов игрока public var id:int;

// Конструктор

public function Item (name:String, src:String, id:int) { this. name = name;

this. src = src; this, id = id;

}

}

}

// Файл QuestionScreen. as package {

import flash. events.*;

import flash. display.*;

import flash. text.*;

import flash. net.*;

// Создает пользовательский интерфейс для вопроса public class QuestionScreen extends Sprite {

private var status:TextField;

private var game:KidsGame;

private var items:Array;

private var thisQuestionltem:Item;

// Конструктор

public function QuestionScreen (game:KidsGame,

items:Array.

Продолжение:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,

41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,

77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,

109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,

135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153

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

ThisQuestionltem:Item) { // Сохраняем ссылку на основной объект игры this. game = game;

// Собираем данные о вопросе this. items = items;

this. thisQuestionltem = thisQuestionltem;

// Помещаем вопрос на экран makeQuestion( );

}

// Создаем и отображаем интерфейс для вопроса public function makeQuestion ( ):void {

// Отображаем картинку для элемента

var imgLoader:Loader = new Loader( );

addChild(imgLoader);

imgLoader. load(new URLRequest(thisQuestionltem. src));

// Добавляем набор слов, которые может выбирать игрок,

// щелкая кнопкой мыши. Для упрощения будем отображать

// название каждого элемента в наборе.

var wordButton:WordButton;

for (var i:int = 0; i < items.length; i++) {

wordButton = new WordButton( );

wordButton. setButtonText(i terns[i].name);

wordButton. setID(items[i].id);

wordButton. у = 110 + i*(wordButton. height + 5);

wordButton. addEventLi stener(MouseEvent. CLICK, cli ckLi stener); addChild(wordButton);

}

// Создаем текстовое поле, в котором будет отображаться статус вопроса

status = new TextFieldC );

status. autoSize = TextFieldAutoSize. LEFT;

status. у = wordButton. у + wordButton. height + 10;

status. selectable = false;

addChild(status);

}

// Отображает сообщение в поле статуса public function displayResult (msg:String):void { status. text = msg;

}

// Выводит выбранное пользователем слово для данного вопроса public function disable ( ):void {

// Отключаем события мыши для всех потомков данного объекта Sprite.

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

MouseChildren = false;

}

// Реагируем на событие, вызванное щелчком кнопкой мыши на кнопке-слове

private function clickListener (е:MouseEvent):void { // Выбранный игроком вариант имеет идентификатор элемента, который был // присвоен объекту WordButton в методе makeQuestion( ). game. submitGuess(е. target. get IDC ));

}

}

}

// Файл WordButton. as package {

import flash. text.*;

import flash. display.*;

// Представляет на экране слово, на котором можно щелкнуть кнопкой мыши // (то есть доступный вариант ответа на вопрос). ID обозначает // идентификатор элемента, выбранного игроком (переменная Item. id), public class WordButton extends Sprite {

private var id:int; // Идентификатор элемента, представляемого // данной кнопкой

private var t:TextField;

// Конструктор

public function WordButton ( ) { t = new TextField( ); t. autoSize = TextFieldAutoSize. LEFT; t. border = true: t. background = true;

t. selectable = false; addChild(t);

buttonMode = true; mouseChildren = false;

}

// Присваивает текст, отображаемый на кнопке public function setButtonText (text:String):void { t. text = text;

}

// Присваивает идентификатор элемента, представляемого данной кнопкой public function setID (newID:int):void { id = newID:

}

// Возвращает идентификатор элемента, представляемого данной кнопкой public function getID ( ):int { return id;

}

}

}

Просмотрели код? Отлично, рассмотрим его более детально. Возможно, вы заметили, что определения пространств имен в игре не изменялись вообще с того момента, как они были представлены в листинге 17.1. Тем не менее существенно изменился класс Items, а также появилось несколько новых классов:

? KidsGame — основной класс приложения;

? I tem — предоставляет информацию о конкретном элементе игры;

? QuestionScreen — формирует пользовательский интерфейс для каждого вопроса;

? WordButton — представляет кнопку-слово на экране.

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

Поскольку сейчас наше внимание сосредоточено на пространствах имен, мы рассмотрим только классы Items и KidsGame. В качестве упражнения рассмотрите оставшиеся классы самостоятельно.

Для начала посмотрим, как изменился класс Items со времени его предыдущего представления в листинге 17.1. Во-первых, мы добавили две новые переменные fruit: : apple и color: : purple, представляющие элементы. Благодаря новым переменным каждая категория элементов для фруктов и цветов теперь состоит из двух элементов: апельсина и яблока для фруктов и оранжевого и фиолетового для цветов. Мы также заменили простые описания элементов из листинга 17.1 (например, Round citrus fruit) экземплярами класса Item. Экземпляры класса Item хранят название элемента, URL-адрес изображения этого элемента и его идентификатор. Следующий код демонстрирует измененные переменные, представляющие элементы. Как и в листинге 17.1, каждая переменная уточняется пространством имен, соответствующим множеству, которому принадлежит данный элемент.

fruit var orange:Item = new Item(«Orange», «fruit-orange. jpg», 1); fruit var apple:Item = new ItemCApple». «fruit-apple. jpg». 2);

color var orange:Item = new Item(«Orange», «color-orange. jpg», 3); color var purple:Item = new ItemC’Purple». «color-purple. jpg», 4);

Кроме того, в класс I terns добавлены два массива, предназначенные для управления элементами в виде групп. Каждый массив содержит полный список элементов своей группы (либо фруктов, либо цветов). Массивы присваиваются переменным с одним и тем же именем (itemSet), но уточняемым различными пространствами имен (fruit и color).

fruit var itemSet:Array = [fruit::orange, fruit::apple]; color var itemSet:Array = [color: :orange, color: .-purple];

Чтобы предоставить доступ другим классам к различным наборам элементов в игре, в Items определено два метода с одним и тем же локальным именем getltems ( ), которое уточняется различными пространствами имен fruit и color. Каждый метод get I terns ( ) возвращает копию набора элементов, соответствующего пространству имен данного метода. Таким образом, обратиться к подходящему набору элементов можно динамически, в зависимости от текущего типа вопроса (либо цвет, либо фрукт).

fruit function getltems ( ):Array { // Возвращает фрукты, return fruit::itemSet. siice(O):

}

color function getltems ( ):Array { // Возвращает цвета, return color::itemSet. slice(0);

}

Наконец, в классе Items определены переменная itemTypes и соответствующий метод-аксессор get ItemTypes ( ). Переменная itemTypes хранит список всех различных множеств элементов в игре. В нашей игре определено только два множества: фрукты и цвета, но в дальнейшем можно будет легко добавить новые множества. Каждое множество элементов соответствует пространству имен, поэтому переменная itemTypes представляет собой массив пространств имен. Метод get ItemTypes ( ) возвращает копию этого массива, предоставляя внешнему коду возможность централизованно получать официальный список типов элементов в игре.

// Переменная itemTypes

private var itemTypes.-Array = [color, fruit]:

// Метод getItemTypes( ) public function getltemTypes ( ):Array { return itemTypes. siice(O);

}

Это все, что касается изменений в классе Items. Теперь рассмотрим новый основной класс приложения KidsGame. В отличие от Items, класс KidsGame никогда не

использует идентификаторы пространств имен fruit и color напрямую. Вместо этого он обращается к указанным пространствам имен через метод экземпляра

getltemTypes ( ) класса Items.



Полезные ссылки
Случайные записи
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.45
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.56
  • 23.07.2011">Обновление линейки Aspire One
  • 12.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.113
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.101
  • 20.01.2010">Векторные файлы и графика
  • 08.03.2011">Руководство по actionscript. часть 4, стр. 081
  • 11.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.25
  • 10.03.2011">Руководство по actionscript. часть 4, стр. 028
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.70
  • 22.03.2011">Руководство по actionscript. часть 2, стр. 022
  • 14.03.2011">Руководство по actionscript. часть 3, стр. 065
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 001
  • 09.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.144
  • 07.03.2011">Руководство по actionscript. часть 4, стр. 119
Опрос

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

View Results

Loading ... Loading ...