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

Взглянем на код в листинге 17.1, после чего рассмотрим его более подробно.

Листинг 17.1. Детская игра: функциональный пример использования пространств имен

// Файл fruit. as package {

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

}

// Файл color. as package {

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

}

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

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

color var orange:String = «Color obtained by mixing red and yellow»;

public function Items ( ) { trace(fruit::orange); trace(color: .-orange);

}

}

}

Предыдущий код начинается с определения пространств имен нашей игры. Пространство fruit определяется в файле fruit, as, как показано в следующем коде:

package {

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

}

После этого мы определяем пространство имен color в файле color. as, как показано в следующем коде:

package {

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

}

Оба пространства имен определены на уровне пакета, поэтому обращаться к ним может любой класс нашего приложения.

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

Затем мы определяем класс Items в файле Items. as. В классе Items определены две переменные, каждая из которых имеет локальное имя orange. Для первой переменной мы указываем уточняющее пространство имен fruit; для второй — уточняющее пространство имен color.

package { public class Items { fruit var orange:String — «Round citrus fruit»; color var orange:String = «Color obtained by mixing red and yellow»;

}

}

Наконец, чтобы убедиться, что наш код работает, в методе-конструкторе класса Items мы используем функцию trace ( ) для отображения значений обеих переменных orange. Чтобы отличать одну переменную orange от другой, используются уточненные идентификаторы fruit: : orange и color: : orange.

package { public class Items {

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

color var orange:String = «Color obtained by mixing red and yellow»;

public function Items ( ) { trace(fruit::orange); // Выводит: Round citrus fruit trace(color::orange); // Выводит: Color obtained by // mixing red and yellow

>

}

}

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

public function Items ( ) { trace(orange); // Что произойдет здесь?

}

Ответ: возникнет следующая ошибка на этапе компиляции программы:

Access of undefined property orange.

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

На русском языке она будет звучать так: Обращение к несуществующему свойству orange.

Компилятор не может найти переменную или метод (то есть «свойство») по имени orange, поскольку в области видимости метода-конструктора Items не существует переменной или метода с простым идентификатором orange. Переменные fruit: : orange и color: : orange уточняются с помощью пространств имен, поэтому они оказываются недоступны при попытке обратиться к ним с применением неуточненного идентификатора. И все-таки далее, в разд. «Открытые пространства имен и директива use namespace», мы познакомимся с упрощенным способом обращения к уточненным идентификаторам без использования уточняющего пространства имен.

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

На этом начальном этапе разработки нашей игры вы могли бы поинтересоваться, почему вместо использования пространств имен мы не можем просто определить переменные с длинными именами, например orangeFruit и orangeColor. Или почему нельзя разделить оба вида oranges, присвоив их двум отдельным массивам, как показано в следующем коде:

var fruitList:Array = ["orange", "apple", "banana"]; var colorList:Array = ["orange", "red", "blue"];

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

Доступность пространств имен

Как и в случае с определениями переменных и методов, определения пространств имен могут быть изменены с помощью модификаторов управления доступом publ i с, internal, protected и private. Местоположение определения пространства имен в сочетании с модификатором управления доступом этого определения указывают, где может быть использован результирующий идентификатор пространства имен.

Вот несколько основных правил, которые помогут решить, где разместить ваши пространства имен.

? Если пространство имен должно быть доступно в любом месте программы или в группе классов, определяйте его на уровне пакета.

? Если вам требуется пространство имен, которое задает видимость переменных и методов внутри одного класса, определяйте его на уровне класса.

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

Рассмотрим несколько примеров, начав с пространств имен, задаваемых на уровне пакета.

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

Доступность определений пространств имен на уровне пакета

В следующем коде мы определяем идентификатор пространства имен fruit в пакете kidsgame:

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

}

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

package anyPackage { // Импортируем пространство имен fruit import kidsgame. fruit;

public class AnyClass { // Здесь можно применять пространство имен fruit, поскольку оно уже // было импортировано

fruit var banana:String = «Long yellow fruit»;

}

}

Теперь сделаем так, чтобы доступность пространства имен color была ограничена одним пакетом, используя модификатор управления доступом internal:

package kidsgame {

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

}

Когда идентификатор пространства имен определяется с применением модификатора управления доступом internal на уровне пакета, он может быть использован только внутри пакета, в котором определен. Это демонстрирует следующий код.

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

Package kidsgame { public class Items { // Здесь можно применять пространство имен color. Использование // пространства имен color допустимо, поскольку оно происходит внутри // пакета kidsgame

color var green:String = «Color obtained by mixing blue and yellow»;

}

}

package cardgame { import kidsgame. col or; public class CardGame { // Недопустимо.

// Пространство имен color может быть использовано // только внутри пакета kidsgame.

color var purple:String = «Color obtained by mixing blue and red»;

}

}

При определении пространств имен на уровне пакета могут применяться модификаторы управления доступом public и internal, при этом использование модификаторов управления доступом private и protected не допускается. Более того, если в определении пространства имен на уровне пакета модификатор управления доступом опускается, применяется модификатор управления доступом internal. Например, следующий код:

package kidsgame { // internal указывается явно internal namespace fruit;

}

аналогичен данному коду:

package kidsgame { // internal подразумевается неявно namespace fruit;

}

Теперь рассмотрим определения пространств имен на уровне класса.

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

Доступность определений пространств имен на уровне класса

Идентификатор пространства имен, определенный в классе с использованием модификатора управления доступом private, доступен только внутри данного класса и недоступен в его подклассах и в любом другом внешнем коде:

public class А { private namespace n = «http://www. example. eom/n»; // Отлично. Идентификатор пространства имен п доступен в этом месте, n var someVariable:int;

}

public class В extends A { // Ошибка. Идентификатор пространства имен п недоступен в этом месте, n var someOtherVariable:int;

}

Мы можем использовать пространство имен, объявленное с применением модификатора управления доступом private, для реализации системы управления доступом на основании разрешений. Эта система рассматривается далее, в подразд. «Пример: управление доступом на основании разрешений» разд. «Практические примеры использования пространств имен».

Идентификатор пространства имен, объявленный в классе с использованием модификатора управления доступом protected, internal или public, доступен напрямую в любом месте данного класса и его подклассов, но недоступен в любом другом внешнем коде. Такое определение пространства имен является противоположностью определения на уровне пакета с применением модификатора управления доступом pub lie, создающего идентификатор пространства имен, к которому можно обращаться напрямую из любого места программы. Это демонстрирует следующий код:

public class А { public namespace n = «http://www. example. eom/n»;

// Отлично. Идентификатор пространства имен п доступен напрямую

// в этом месте.

n var someVariable:int;

}

public class В extends A { // Отлично. Идентификатор пространства имен п доступен напрямую // в этом месте, n var someOtherVariable:int;

}

public class С {

// Ошибка. Идентификатор пространства имен п напрямую не доступен // в этом месте.

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

// (Но идентификатор п мог бы быть доступен, если бы он был определен

// на уровне пакета.)

n var yetAnotherVariable:int;

}

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

Например, чтобы обратиться к объекту Namespace, на который ссылается идентификатор пространства имен п в предыдущем коде, мы могли бы использовать выражение: А. п. Доступ к объектам Namespace с помощью синтаксиса обращения к статическим переменным регламентируется обычными ограничениями, налагаемыми на статические переменные, объявленные с применением модификаторов управления доступом protected, internal и public. В предыдущем коде, поскольку идентификатор п объявлен с использованием модификатора управления доступом public, выражение А. п является допустимым в любом коде, который имеет доступ к классу А. Если бы идентификатор п был объявлен с использованием’ модификатора управления доступом internal, выражение А. п было бы допустимым только внутри пакета, содержащего определение данного пространства имен. Если бы идентификатор п был объявлен с использованием модификатора управления доступом protected, выражение А. п было бы допустимым только внутри класса А и его подклассов.

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

А. п var p:int; // Недопустимо. А. п не является константой // на этапе компиляции.

Итак, если мы не можем использовать выражение А. п для уточнения определений, для чего оно может использоваться вообще? Оставайтесь с нами, мы скоро узнаем ответ на этот вопрос в разд. «Присваивание и передача значений пространств имен».

Пока рассмотрим последнюю тему, связанную с доступностью пространств имен: определение пространств имен в методах и функциях.

Доступность определений пространств имен на уровне функции

Как и в случае с другими определениями на уровне функции, идентификатор пространства имен, объявленный на уровне функции, не может включать никакие модификаторы управления доступом (то есть он не может быть объявлен с использованием модификаторов управления доступом public, private и т. д.) и доступен только в области видимости данной функции:

public function doSomething ( ):void { // Это недопустимо

private namespace n = «http://www. example. eom/n»;

}

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

public function doSomething ( ):void { // Это тоже недопустимо namespace n = «http://www. example. eom/n»; n var someLocalVariable:int = 10;

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

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

Public function doSomething ( ):void { // Это допустимо

namespace n = «http://www. example. eom/n»; trace(n: .-someVariable) ;

}

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

public function getPrice ( ):void { namespace htmlNS = «http://www. w3.org/1999/xhtml»; output. text = htmlNS::table. htmlNS::tr[l].htmlNS::td[l].price;

}

Пространства имен XML будут рассматриваться в гл. 18.

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

Наверняка вы заметили, что в этой книге определения уточненных идентификаторов не включают модификаторы управления доступом (public, internal, protected или private). Мы видели достаточно много таких определений:

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

Однако ни одного такого (обратите внимание на присутствие модификатора управления доступом private):

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

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

private, fruit var orange:String;

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

Access specifiers not allowed with namespace attributes

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

Руководство по 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, пространства имен могут присваиваться переменным или элементам массива, передаваться в методы и возвращаться из методов и вообще могут быть использованы, как любой другой объект. Эта гибкость позволяет:

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

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



Полезные ссылки
Случайные записи
  • 24.02.2011">Руководство по actionscript. часть 6, стр. 114
  • 09.03.2011">Руководство по actionscript. часть 4, стр. 060
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.97
  • 11.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.26
  • 06.03.2011">Руководство по actionscript. часть 4, стр. 148
  • 22.03.2011">Руководство по actionscript. часть 2, стр. 025
  • 04.06.2012">Судья заявил, что у Oracle нет авторских прав на Java API
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 125
  • 12.04.2011">Photoshop для начинающих: как вставить фото в готовую рамку?
  • 06.04.2010">Бесплатные шрифты
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.51
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.116
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.50
  • 04.03.2011">Руководство по actionscript. часть 5, стр. 029
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.98
Опрос

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

View Results

Loading ... Loading ...