Март 2011

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

Когда среда выполнения проверяет существование переменной description в открытых пространствах имен, она находит два соответствия: private : .-description и protected: :description класса Child. Как мы уже знаем из предыдущего раздела, когда неуточненная ссылка соответствует имени в более чем одном пространстве имен, возникает ошибка неоднозначного обращения. Более того, если несколько имен уточняются различными неявно открытыми пространствами имен, возникает ошибка, связанная с конфликтом определений. В случае с переменной description возникнет следующая ошибка:

A conflict exists with inherited definition Parent. description in namespace protected.

На русском языке она будет выглядеть так: Существует конфликт с унаследованным определением Parent. description в пространстве имен protected.

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

package { import flash. display.*; public class SomeClass extends Sprite { private var prop:int;

private var prop:int; // Недопустимое повторное определение свойства

}

}

вызовет следующую ошибку:

A conflict exists with definition prop in namespace private.

По-русски это будет звучать так: Существует конфликт с определением prop в пространстве имен private.

На самом деле из-за ошибки компилятора в приложениях Flex Builder 2 и Flash CS3 предыдущее сообщение будет содержать неправильную фразу namespace internal, хотя должно быть namespace private.

Подобным образом, данный код:

package { import flash. display.*; public class SomeClass extends Sprite { private var x;

вызовет следующую ошибку (поскольку — об этом вы можете почитать в справочнике по языку ActionScript компании Adobe — в классе Di splayOb j ect уже определена переменная х с использованием модификатора управления доступом public):

A conflict exists with inherited definition f1 ash. di splay:Di splayObject. x in namespace public.

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

На русском языке это будет выглядеть следующим образом: Существует конфликт с унаследованным определением flash. display:DisplayObject. x в пространстве имен public.

Директива import открывает пространства имен public. Стоит отметить, что с технической точки зрения импортирование пакета, как показано в следующем коде:

import somePackage.*;

открывает пространство имен public импортированного пакета. Тем не менее оно не открывает пространство имен internal импортированного пакета. Даже если пакет импортируется, его идентификаторы, объявленные с использованием модификатора управления доступом internal, остаются недоступными для внешнего кода.

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

В самом начале этой главы упоминалось четыре практических сценария использования пространств имен:

? предотвращение конфликтов именования;

? управление видимостью членов на уровне прикладной среды;

? управление доступом на основании разрешений;

? реализация различных режимов работы программы.

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

Пример: управление видимостью на уровне прикладной среды

Наш первый пример прикладного использования пространств имен взят из прикладной среды Flex компании Adobe — это библиотека компонентов пользовательского интерфейса и утилит для разработки интернет-приложений с широкими функциональными возможностями.

Прикладная среда Flex включает большое количество кода — сотни классов, размещаемых в дюжинах пакетов. Некоторые методы и переменные этих классов должны быть доступны в различных пакетах, но при этом они должны считаться внутренними по отношению ко всей прикладной среде. Возникает дилемма: если методы и переменные объявить с использованием модификатора управления до-

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

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

Для разрешения этой ситуации в прикладной среде Flex определяется пространство имен mx internal, используемое для уточнения методов и переменных, которые не должны быть видны за пределами прикладной среды, но при этом должны быть доступны в различных пакетах внутри ее.

Вот объявление пространства имен mx internal:

package mx. core { public namespace mx_internal =

«http://www. adobe. com/2006/f1ex/mx/i nternal»;

}

Рассмотрим конкретный пример использования пространства имен mx internal из прикладной среды Flex.

Для работы с табличными данными наподобие тех, которые используются в программах электронных таблиц, прикладная среда Flex предоставляет компонент DataGr id. Класс DataGrid находится в пакете mx. controls. Вспомогательные классы для компонента Dat aGr id размещаются в отдельном пакете:mx. controls. gridclasses. Чтобы взаимодействие между классом DataGrid и его вспомогательными классами осуществлялось максимально эффективно, DataGrid обращается к некоторым внутренним переменным его вспомогательных классов напрямую, а не с помощью доступных всем методов-получателей. Однако эти внутренние переменные не должны использоваться классами за пределами прикладной среды Flex, поэтому они уточняются пространством имен mx internal. Например, вспомогательный класс mx. controls. gridclasses. DataGridColumn хранит индекс столбца в переменной mx_internal: : colNum.

// Файл DataGridColumn. as mx_internal var colNum:Number;

Чтобы получить индекс столбца, класс DataGrid сначала открывает пространство имен mx_internal:

use namespace mx_internal;

а затем обращается к переменной mx internal: : colNum напрямую, как показано в следующем фрагменте кода, взятого из определения метода-писателя:

// Файл DataGrid. as

public function set columns(value:Array):void { // Инициализируем «colNum» для всех столбцов var n:int = value. length; for (var i:int = 0; i < n; i++) {

var column:DataGridColumn = _columns[i];

column. owner = this;

// Обращаемся к переменной mx_internal::colNum напрямую. (Напомним, что

// пространство имен mx_internal открыто, поэтому выражение

// column. colNum эквивалентно выражению column. mx_internal: .colNum.)

column. colNum = i;

}

// Оставшаяся часть метода не приводится

}

Классы за пределами прикладной среды Flex для получения индекса столбца используют общедоступный метод getColumnlndex ( ) вместо обращения к переменной mx_internal: : colNum напрямую.

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

Проблема решена на 9/10. Помещение переменных и методов в пространство имен mx internal, безусловно, уменьшает их непосредственную видимость, однако технически это не запрещает коду за пределами прикладной среды Flex обращаться к ним. Любой разработчик, которому известен идентификатор URI пространства имен mx_internal, может применять этот идентификатор для обращения к любой переменной или методу, уточняемому с использованием пространства имен mx_internal.

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

Пример: управление доступом на основании разрешений

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

Защищаемый класс — класс, который предоставляет доступ к своим защищенным методам и переменным.

Методы и переменные с ограниченным доступом — группа методов и переменных, доступ к которым ограничен.

Авторизованные классы — классы, которым разрешен доступ к методам и переменным с ограниченным доступом.

Рассмотрим базовый код защищаемого класса:

package { // Это защищаемый класс, public class ShelteredClass {

// Пространство имен restricted уточняет переменные

// и методы, доступ к которым ограничен.

private namespace restricted;

// Это массив авторизованных классов. В данном примере // определен только один авторизованный класс: Caller, private var authorizedClasses:Array = [ Caller ];

// Это переменная с ограниченным доступом.

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

// классы.

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

Restricted var secretData:String = «No peeking»;

// Это метод с ограниченным доступом.

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

// классы.

restricted function secretMethod ( ).void { trace(«Restricted method secretMethod( ) called»);

}

}

}

Защищаемый класс хранит массив авторизованных классов. Кроме того, в нем объявлено пространство имен с использованием модификатора управления доступом private, которое применяется для уточнения методов и переменных с ограниченным доступом. Более того, идентификатор URI для этого пространства имен генерируется автоматически, поэтому его невозможно узнать и использовать за пределами данного класса. Наконец, защищаемый класс определяет сами переменные и методы с ограниченным доступом.

Для обращения к методу или переменной с ограниченным доступом (например, secretData или secretMethod ( ) ) потенциальный класс должен получить общеизвестные «ключи от парадной двери». Другими словами, он должен получить ссылку на пространство имен, которое уточняет методы и переменные с ограниченным доступом. Однако защищаемый класс предоставит эту ссылку только в том случае, если потенциальный класс — будем называть его «вызывающим классом» — является одним из элементов массива authorizedClasses.

В нашем примере вызывающий класс будет просить у класса ShelteredClass ссылку на пространство имен restricted, используя метод getRestricted Namespace ( ) класса ShelteredClass. Метод getRestrictedAccess ( ) принимает экземпляр вызывающего класса в качестве аргумента. Если экземпляр вызывающего класса оказывается авторизованным, метод getRestrictedNames расе ( ) вернет ссылку на пространство имен restricted. В противном случае метод вернет значение null, которое сообщает о том, что вызывающий класс не имеет права обращаться к методам и переменным с ограниченным доступом. Рассмотрим код метода getRestrictedNamespace ( ):

public function getRestrictedNamespace

(cal lerObject:Object.):Namespace { // Проверяем, есть ли объект cal1erObject в массиве authorizedClasses. for each (var authorizedClass:Class in authorizedClasses) { // Если вызывающий объект является экземпляром авторизованного класса… if (callerObject is authorizedClass) { // …возвращаем обратно ссылку на пространство имен restricted // («ключи от парадной двери») return restricted;

// Вызывающий объект не является экземпляром

// авторизованного класса, поэтому

// запрещаем дальнейшее обращение к переменной

// и методу с ограниченным доступом.

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

Return null;

}

В листинге 17.5 продемонстрирован весь код класса ShelteredClass, включая метод getRestrictedNamespace ( ).

Листинг 17.5. Класс ShelteredClass

package { // Это защищаемый класс public class ShelteredClass {

// Пространство имен restricted уточняет переменные

// и методы, доступ к которым ограничен.

private namespace restricted;

// Это массив авторизованных классов. В данном примере // определен только один авторизованный класс: Caller, private var authorizedClasses:Array = [ Caller ];

// Это переменная с ограниченным доступом.

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

restricted var secretData.-String = «No peeking»;

// Это метод с ограниченным доступом. // К нему могут обращаться только авторизованные классы, restricted function secretMethod ( ):void { trace(«Restricted method secretMethod( ) called»);

}

public function getRestrictedNamespace

(callerObject:Object):Namespace { // Проверяем, есть ли объект callerObject в массиве authorizedClasses. for each (var authorizedClass:Class in authorizedClasses) { // Если вызывающий объект является экземпляром // авторизованного класса… if (cal1erObject is authorizedClass) { // …возвращаем обратно ссылку на пространство имен restricted // («ключи от парадной двери») return restricted;

}

}

// Вызывающий объект не является экземпляром // авторизованного класса, поэтому // запрещаем дальнейшее обращение к переменной // и методу с ограниченным доступом, return null;

Теперь рассмотрим класс Caller — класс, который желает получить доступ к методам и переменным с ограниченным доступом класса Shel teredClas s. Принимая во внимание значения элементов массива authorizedClasses класса ShelteredClass, мы знаем, что класс Caller является допустимым. В нашем примере Caller также является основным классом приложения, поэтому он расширяет класс Sprite. Класс Caller создает экземпляр класса ShelteredClass в своем методе конструктора и присваивает этот экземпляр переменной shelteredOb j ect.

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

Package { import flash. display.*;

public class Caller extends Sprite { private var shelteredObject:ShelteredClass;

public function Caller ( ) { shelteredObject = new ShelteredClass( );

}

}

}

Чтобы вызвать метод secretMethod ( ) класса ShelteredClass, объект Caller должен сначала получить ссылку на пространство имен restricted. Для этого объект Caller передает себя в метод getRestrictedNamespace ( ) и присваивает результат (либо пространство имен restricted, либо значение null) переменной key для дальнейшего использования.

var key:Namespace = shelteredObject. getRestrictedNamespace(this);

Далее, перед тем как вызвать метод secretMethod ( ), объект Caller проверяет, ссылается ли переменная key на допустимое пространство имен. Если это так, объект Caller использует переменную key в качестве пространства имен для вызова метода secureMethod ( ):

if (key!= null) { shelteredObject. key::secureMethod( );

}

Для удобства метод с именем callSecretMethod ( ) нашего класса Caller включает код, который вызывает метод secretMethod ( ):

public function callSecretMethod ( ):void { var key:Namespace = shelteredObject. getRestrictedNamespace(this); if (key!= null) { shelteredObject. key:: secretMethod( );

}

}

Листинг 17.6 демонстрирует весь код рассматриваемого класса Caller, включая метод callSecretMethod ( ) и другой удобный метод displaySecret ( ), который обращается к переменной secretData с ограниченным доступом, используя тот же основной принцип.

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

Листинг 17.6. Класс Caller

package { import flash. display.*;

public class Caller extends Sprite {

private var shelteredObject:ShelteredClass;

public function Caller ( ) { shelteredObject = new ShelteredClass( ); callSecretMethod( ); displaySecret( );

}

public function callSecretMethod ( ):void { var key-.Namespace = shelteredObject. getRestrictedNamespace(this) ; if (key!= null) { shelteredObject. key::secretMethod( );

}

}

public function displaySecret ( ):void { var key:Namespace = shelteredObject. getRestrictedNamespace(this); if (key!= null) { trace(shelteredObject. key. :secretData);

}

}

}

}

Пример: реализация режимов работы программы

Последним рассматриваемым примером будет электронный словарь, который позволяет переводить с японского языка на английский и наоборот. Словарь демонстрирует использование режимов программы — область программирования на языке ActionScript, где применяются пространства имен, с самым большим потенциалом. Находясь в «режиме японского языка», словарь возвращает английский перевод для японских слов; находясь в «режиме английского языка», словарь возвращает японский перевод для английских слов. Каждый режим представляется пространством имен: j apanese для японско-английского режима и english для англо-японского режима.

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

В этом примере задействованы следующие участники:

? Japane se — пространство имен для переменных и методов, относящихся к японскому языку;

? English — пространство имен для переменных и методов, относящихся к английскому языку;

? QueryManager — класс, осуществляющий поиск слов;

? SearchOptions — этот класс содержит базовые настройки для операции поиска;

? JapaneseSearchOptions — класс, содержащий настройки, характерные для операции поиска на японском языке;

? Engl ishSearchOpt ions — данный класс хранит настройки, характерные для операции поиска на английском языке;

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

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

Начнем с рассмотрения определений пространств имен japanesenenglish, чей код уже должен быть вам знаком:

package {

public namespace english = «http://www. example. com/jedict/english»;

}

package {

public namespace japanese = «http://www. example. com/jedict/japanese»;

}

Далее идет класс QueryManager, который определяет два метода для поиска слова, — japanese: : search ( ) и english: : search ( ). Вызов подходящего метода происходит в зависимости от текущего режима программы. Каждый метод search ( ) принимает apryMeHT’options, который определяет настройки поиска в виде либо объекта класса JapaneseSearchOptions, либо объекта класса EnglishSearchOpt ions соответственно. Далее при рассмотрении класса JEDictionary мы увидим, что настройки поиска выбираются в соответствии с текущим режимом программы. Вот код класса QueryManager:

package { public class QueryManager {

japanese function search (word:String.

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

Options.-JapaneseSearchOptions): Array { trace («Now searching for ‘» + word + ‘»An»

+ » Match type: » + options. getMatchType( ) + «\n»

+ » English language variant: » + options. getEnglishVariant( ));

// Расположенный здесь код (не показан) должен выполнять поиск // в японско-английском словаре и возвращать результаты. * // но для эксперимента мы будем просто возвращать предопределенный // список результатов:

return ["English Word 1". "English Word 2". "etc"];

}

english function search (word.-String.

options:Engl ishSearchOptions):Array { traceCNow searching for ‘» + word + ‘»An»

+ » Match type: » + options. getMatchType( ) + «\n»

+ » Use kanji in results: » + options. getKanjiInResults( ));

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

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

return ["Japanese Word 1", "Japanese Word 2". "etc"];

}

}

}

Теперь рассмотрим три класса, предоставляющие настройки поиска: SearchOptions и два его подкласса JapaneseSearchOptions и EnglishSearchOptions. Класс SearchOptions задает, с использованием какого режима программа должна выполнять поиск указанной строки: «точного совпадения» (искомое слово должно полностью совпадать со строкой поиска), «совпадает начало» (все искомые слова должны начинаться со строки поиска) или «содержит совпадение» (все искомые слова должны включать строку поиска).



Полезные ссылки
Случайные записи
  • 17.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.113
  • 14.03.2011">Руководство по actionscript. часть 3, стр. 073
  • 15.03.2011">Руководство по actionscript. часть 3, стр. 053
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.56
  • 21.03.2010">Интересные заметки за февраль
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 058
  • 26.02.2011">Руководство по actionscript. часть 6, стр. 073
  • 17.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.123
  • 19.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.34
  • 11.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.39
  • 03.03.2012">Windows 8 готовит смерть Android-планшетам
  • 02.03.2011">Руководство по actionscript. часть 5, стр. 091
  • 11.03.2011">Руководство по actionscript. часть 4, стр. 003
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 092
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 093
Опрос

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

View Results

Loading ... Loading ...