Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Пространства имён (Namespaces) (http://www.flasher.ru/forum/showthread.php?t=111988)

moron 14.05.2008 17:40

Пространства имён (Namespaces)
 
Перевёл статью http://www.adobe.com/livedocs/flash/...=00000042.html

Пространства имён
Пространства имён позволяют контролировать видимость создаваемых свойств и методов. Можно сказать, что public, private, protected, internal являются встроенными идентификаторами пространств имён(это пространства имён контроля доступа). Если они не удовлетворяют ваши нужды – вы можете создать собственные.

Имя свойства или метода всегда состоит из двух частей: идентификатор и пространство имён. В следующем примере идентификаторами являются sampleGreeting и sampleFunction():
Код:

class SampleCode
{
    var sampleGreeting:String;
    function sampleFunction () {
        trace(sampleGreeting + " from sampleFunction()");
    }
}

Если определению идентификатора не предшествует атрибут пространства имён, то он рассматривается как идентификатор в пространстве имён internal – это значит, что данное имя видно только caller'ам внутри данного пакета. Если режим компилятора «стогий», то он выдаст предупреждение, что всякий идентификатор без атрибута простанства имён будет internal. Дабы обеспечить видимость отовсюду, нужно явно указывать атрибут public. В предыдущем примере идентификаторы sampleGreeting и sampleFunction()имеют атрибут internal.

Существует три основных момента при использовании собственных пространств имён.
Во-первых, определение пространства имён нужно начинать с ключевого слова namespace. В следующем примере определяется пространство имён version1:
Код:

namespace version1;
Во-вторых, чтобы применять своё пространство имён, нужно использовать его в качестве атрибута пространства имён у определяемых переменных и свойств. В следующем примере функция располагается в пространстве имён version1:
Код:

version1 function myFunction() {}
В-третьих, после того, как вы применили своё пр.имён, на него можно ссылаться использую директиву use или же квалифицируя идентификатор пространством имён. Следующий пример ссылается на функцию myFunction() через директиву use namespace:
Код:

use namespace version1;
myFunction();

Также можно ссылаться на функцию myFunction(), используя соответсвующий квалификатор:
Код:

version1::myFunction();

moron 14.05.2008 17:42

Определение пространств имён
Пространствоа имён содержат одну величину, Uniform Resource Identifier (URI), также называемую именем пространства имён. URI обеспечивает уникальность определения пространства имён.
Создать пространства имён путём обьявления определения пространства имён можно одним из двух способов. Можно либо определить пр.имён явно указав URI, либо не указывая URI. Пример явного указания URI:
Код:

namespace flash_proxy = "http://www.adobe.com/flash/proxy";
URI служит уникальной идентификационной строкой для этого пр.имён. Если не указывать URI, то компилятор создаст внутреннюю уникальную идентификационную строку вместо URI. Внешний доступ к этой внутренней строке в этом случае закрыт:
Код:

namespace flash_proxy;
Определив пр.имён, указывая URI или не указывая, это пр.имён не может больше быть переопределено в данных пределах (in the same scope). Попытка определить уже определённое ранее пр.имён приведёт к ошибке компилятора.
Если пр.имён определено внутри пакета или класса, оно не видно для кода снаружи пакета или класса, если соответствующий спецификатор доступа не был использован. В следующем примере пр.имён flash_proxy определено внутри пакета flash.utils:
Код:

package flash.utils
{
    namespace flash_proxy;
}

Слудующий код использует атрибут public для того, чтобы пр.имён flash_proxy было видно для кода вне пакета:
Код:

package flash.utils
{
    public namespace flash_proxy;
}

Применение пространств имён
Применение пространства имён подразумевает под собой помещение определения в пространство имён. Определения, которые могут быть помещены в пр.имён, включают функции, переменные и константы(нельзя поместить класс в собственное пр.имён).
Рассмотрим, к примеру, функцию, объявленную с использованием атрибута доступа public. Эта функция помещается в пр.имён public, что делает функцию доступной для всего кода. После определения собственного пр.имён, можно использовать его также, как используется атрибут public, и определение будет доступно коду, который может ссылаться на ваше пр.имён. Например, после определния пр.имён example1, можно добавить метод myFunction() используя example1 как атрибут:
Код:

namespace example1;
class someClass
{
    example1 myFunction() {}
}

Определение метода myFunction(), с использованием пр.имён example1 как атрибута, означает, что метод принадлежит пр.имён example1.
При применении пр.имён следует помнитьследующее:
1.) Только одно пр.имён может быть применено к каждому обьявлению
2.) Нельзя применить пр.имён сразу к нескольким определениям за раз. Другими словами, если вы хотите применить пр.имён к десяти различным функциям, вы должны будете добавить атрибут пр.имён к каждому из десяти определений функций.
3.) При использовании пр.имён, нельзя вместе с пр.имён указывать спецификатор доступа, т.к. пр.имён и спецификаторы доступа являются взаимоисключающими. Другими словами, нельзя объявить функцию или свойство как public, private, protected или internal вместе с применением пр.имён.

Обращение к пространствам имён
Нет необходисмости в явном обращении к пр-ву имён когда используется метод или свойство, объявленные с помощью какого-либо пр.имён контроля доступа, т.е. с помощью атрибутов public, private, protected и internal. Доступ к этим специальным пр-вам имён контроллируется по контексту. К примеру, определения, помещённые в пр-во имён private автоматичеки доступны коду внутри данного класса. Для пр-в имён, которые вы определяете сами, однако, такой зависимости от контекста не существует. Для того, чтобы использовать метод или свойство, помещённые в ваши пр-ва имён, нужно ссылаться на эти пр-ва имён.
Ссылаться на пр-ва имён можно с помощью директивы use namespace или же определяя имя пр-вом имён используя именной спецификатор (::) пунктуатор. Ссылка на пр-во имён с помощью директивы use namespace «открывает» пр-во имён, так что она может быть использована для всякого идентификатора, который не квалифицирован. Например, если определено пр-во имён example1, то доступ к именам в этом пр-ве имён можно осуществлять при помощи use namespace example1:
Код:

use namespace example1;
myFunction();

Можно открывать несколько пр-в имён за раз. После того как вы открыли пр-во имён с помощью use namespace, оно остаётся открытым на протяжении всего блока кода, в котором оно было открыто. Нельзя явно закрыть пр-во имён.
Наличие более одного открытого пр-ва имён, однако, повышает вероятность конфликтов имён. Если вы предпочтёте не открывать пр-во имён, то можно избежать использование директивы use namespace квалифицируя имя метода или свойства пр-вом имён квалифицирующим именным пунктуатором:
Код:

example1::myFunction();

moron 14.05.2008 17:43

Использование пространств имён
Практические примеры пр-в имён, которые используются для предотвращения конфликтов имён, можно найти в классе flash.utils.Proxy, который является частью Flash Player API. Класс Proxy, заменяющий свойство Object.__resolve из ActionScript 2.0, позволяет перехватывать ссылки на неопределённые свойства и методы перед возникновением ошибок. Все методы класса Proxy находятся в пространстве имён flash_proxy для предотвращения конфликтов имён.
Для лучшего понимая того, как используется пр-во имён flash_proxy, необходимо понять как использовать класс Proxy. Выполняемые функции класса Proxy доступны только для классов, которые от него наследуются. Другими словами, если вы хотите использовать методы класса Proxy на объекте, определение класса объекта должно расширять класс Proxy. К примеру, если нужно перехватить попытки вызова неопределённого метода, следует расширить класс Proxy и затем переопределить метод callProperty() этого класса.
Вы, наверное, помните, что реализация пр-в имён – это обычно трёхшаговый процесс определения, применения, а затем ссылки на пр-во имён. Так как методы класса Proxy никогда не вызываются явно, пр-во имён flash_proxy, однако, только определяется, применяется, но на него никогда не ссылаются. Flash Player API определяет пр-во имён flash_proxy и применяет его в классе Proxy. Ваш код нуждается только лишь в применении пр-ва имён flash_proxy к классам, которые расширяют класс Proxy.
Пространство имён flash_proxy определено в пакете flash.utils примерно следующим образом:
Код:

package flash.utils
{
    public namespace flash_proxy;
}

Пространство имён применяется к методам класса Proxy как показано в следующем отрывке из класса Proxy:
Код:

public class Proxy
{
    flash_proxy function callProperty(name:*, ... rest):*
    flash_proxy function deleteProperty(name:*):Boolean
    ...
}

Как показано в нижеследующем коде, необходимо сначала импортировать класс Proxy и пр-во имён flash_proxy. Затем необходимо объявить свой класс так, чтобы он расширял класс Proxy (также необходимо добавлять атрибут dynamic , если режим копилятора «строгий»). При переопределении метода callProperty(), необходимо использовать пр-во имён flash_proxy:
Код:

package
{
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;

    dynamic class MyProxy extends Proxy
    {
        flash_proxy override function callProperty(name:*, ...rest):*
        {
            trace("method call intercepted: " + name);
        }
    }
}




Если создать экземпляр класса MyProxy и вызвать неопределённый метод, такой как метод testing(), вызывающийся в следующем примере, ваш Proxy объект перехватит вызов метода и выполнит выражения внутри переопределённого метода callProperty() (в данном случае просто вызывается метод trace()):
Код:

var mySample:MyProxy = new MyProxy();
mySample.testing(); // method call intercepted: testing

Есть два преимущества в расположении методов класса Proxy внутри пр-ва имён flash_proxy. Во-первых, наличие отдельного пр-ва имён уменьшает беспорядок в открытых интерфейсах всяких классов, расширяющих класс Proxy. (В классе Proxy можно переопределить дюжину методов, куждый из которых не предназначен для прямого вызова. Помещение всех их в пр-во имён public сбивало бы с толку.) Во-вторых, использование пр-ва имён flash_proxy предотвращает конфликты имён в случае если ваш Proxy подкласс содержит методы экземпляров, имена которых совпадают с именами методов класса Proxy. Например, вы можете захотеть назвать один из своих методов именем callProperty(). Следующий код допустим, так как ваша версия метода callProperty() находится в другом пр-ве имён:
Код:

dynamic class MyProxy extends Proxy
{
    public function callProperty() {}
    flash_proxy override function callProperty(name:*, ...rest):*
    {
        trace("method call intercepted: " + name);
    }
}

Пространства имён также могут быть полезны, когда требуется обеспечить доступ к методам или свойствам способом, который не может быть совершён при использовании четырёх спецификаторов доступа(public, private, internal и protected) . К примеру, имеется несколько полезных методов которые распределены по нескольким пакетам. Вы хотите, чтобы эти методы были доступны всем вашим пакетам, но не хотите, чтобы они были открытыми. Достигнуть этого можно путём создания новых пр-в имён и использования их как своих собственных специальных спецификаторов доступа.
Следующий пример использует пользовательское пр.имён, чтобы сгруппировать вместе две функции, расположенные в различных пакетах. Группируя их в одно пр-во имён, можно сделать обе функции видимыми классу или пакету одним выражением use namespace.
Этот пример четыре файла для демонстрации такого способа. Все файлы должны находиться внутри вашей классовой директории. Первый файл, myInternal.as, используется для определения пр-ва имён myInternal. Так как файл находится в пакете example, необходимо поместить файл в каталог, названный example. Пр-во имён помечено как public, поэтому оно может быть импортировано в другие пакеты.
Код:

// myInternal.as in folder example
package example
{
    public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples";
}

Второй и третий файлы, Utility.as и Helper.as, определяют классы, содержащие методы, которые нужно сделать доступными другим пакетам. Класс Utility находится в пакете example.alpha, т.е. нужно поместить файл в каталог alpha, являющийся подкаталогом каталога example. Класс Helper находится в пакете example.beta, т.е. нужно поместить файл в каталог beta, являющийся подкаталогом каталога example. Оба этих пакета, example.alpha и example.beta, должны импортировать пр-во имён перед тем, как его использовать.
Код:

// Utility.as in the example/alpha folder
package example.alpha
{
    import example.myInternal;
   
    public class Utility
    {
        private static var _taskCounter:int = 0;
   
        public static function someTask()
        {
            _taskCounter++;
        }
       
        myInternal static function get taskCounter():int
        {
            return _taskCounter;
        }
    }
}

// Helper.as in the example/beta folder
package example.beta
{
    import example.myInternal;
   
    public class Helper
    {
        private static var _timeStamp:Date;
       
        public static function someTask()
        {
            _timeStamp = new Date();
        }
       
        myInternal static function get lastCalled():Date
        {
            return _timeStamp;
        }
    }
}

Четвёртый файл, NamespaceUseCase.as, является главным классом приложения и должен располагаться по соседству с каталогом example. В Adobe Flash CS3 Professional, этот класс будет использован как класс документа для FLA. Класс NamespaceUseCase также импортирует пространство имён myInternal и использует его для вызова двух статичеких методов, расположенных в других пакетах. В примере статичекие методы используются лишь для упрощния кода. И статический метод, и метод экземпляра могут быть помещены в пр-во имён myInternal.
Код:

// NamespaceUseCase.as
package
{
    import flash.display.MovieClip;
    import example.myInternal;      // import namespace
    import example.alpha.Utility;    // import Utility class
    import example.beta.Helper;      // import Helper class
   
    public class NamespaceUseCase extends MovieClip
    {
        public function NamespaceUseCase()
        {
            use namespace myInternal;
           
            Utility.someTask();
            Utility.someTask();
            trace(Utility.taskCounter); // 2
           
            Helper.someTask();
            trace(Helper.lastCalled);  // [time someTask() was last called]
        }
    }
}



Часовой пояс GMT +4, время: 01:10.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.