воскресенье, 17 августа 2008 г.

Права доступа ActionScript 3.0

В ActionScript 3 добавлено два новых ключевых слова для описания прав доступа и усовершенствовано свойство private по сравнению с ActionScript 2. Итак, теперь мы имеем следующие ключевые слова для регулирования прав доступа:



  • public

  • protected

  • private

  • internal (по умолчанию)


public: то же самое, что и в ActionScript 2, все определенное как public может быть прочитано откуда угодно.
Конструкторы теперь всегда public.

protected: новое ключевое слово, указывает, что метод или переменная скрыта от всех кроме классов потомков.
Классы и конструкторы не могут быть определены как protected.

private: в ActionScript 2 было это ключевое свойство, но фактически работало как protected, т.е. классы потомки имели полный доступ к методу или свойству, описанному как private. Теперь в ActionScript 3 private это полноценная приватность, т.е. доступ только в этом классе, в котором метод или переменная описана, для всех остальных, включая потомков, она не будет существовать. Это означает, что в классе-потомке можно объявить еще одну переменную или метод с таким же именем и при этом не возникнет никаких конфликтов.
Классы и конструкторы не могут быть определены как private.

internal: аналогично public, но ограничено пределами пакета (package). Только классы, описанные в этом же пакете, будут иметь доступ к internal переменным или методам.
Internal ставится по умолчанию для любого класса, переменным или методам класса, кроме конструкторов, которые всегда public.

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

В ActionScript 3 проверка прав доступа осуществляется не только на этапе компиляции, но и при выполнении, т.е. хаки использовавшиеся в ActionScript 2, чтобы получить доступ к скрытым методам больше не будут работать.

Рассмотрим все это на примерах.
Пример 1.


Код:



package {


   


    import flash.display.Sprite;


   


    // Класс AccessControl  объявлен как public (по умолчанию был бы internal)


    public class AccessControl extends Sprite {


       


        // Конструктор всегда public


        function AccessControl() {


           


            // Только классы описанные в этом файле


            // имеют доступ к вспомогательным классам


            var helper:Helper = new Helper();


           


            trace(helper.pubNum); // OK - это public


            // trace(helper.protNum); // Error – нет доступа к protected


            // trace(helper.privNum); // Error – нет доступа к private


            trace(helper.interNum); // OK - это internal


        }


    }


}


 


// Класс Helper по умолчанию internal


class Helper {


   


    // public – переменная видна отовсюду


    public var pubNum:Number = 1;


   


    // protected – доступ только из классов потомков


    protected var protNum:Number = 2;


   


    // private – доступно только в этом классе


    private var privNum:Number = 3;


   


    // internal – доступно только в этом же package,


    // но для вспомогательного класса это означает,


    // что только для классов описанных в этом файле


    internal var interNum:Number = 4;


       


    // Конструктор всегда public


    function Helper() {


    }


}


 


// класс SubHelper будет internal


// Потомок вспомогательного класса Helper


class SubHelper extends Helper {


   


    // Конструктор всегда public


    function SubHelper() {


        trace(pubNum); // OK – это public


        trace(protNum); // OK – т.к. мы являемся потомком


        // trace(privNum); // Error – нет доступа к private


        trace(interNum); // OK – в этом же файле


    }


}



Пример 2.


Код:



package {


   


    import flash.display.Sprite;


    import containers.*; // описано ниже


   


    // Класс AccessControl  объявлен как public (по умолчанию был бы internal)


    public class AccessControl extends Sprite {


       


        // Конструктор всегда public


        function AccessControl() {


           


            // Есть доступ из другого пакета (packages)


            // только если класс public


            var bowl:Bowl = new Bowl(); // OK


            // var basket:Basket = new Basket(); // Error – нет доступа к internal


           


            trace(bowl.pubNum); // OK


            // trace(bowl.protNum); // Error - нет доступа к protected


            // trace(bowl.privNum); // Error - нет доступа к private


            // trace(bowl.interNum); // Error - нет доступа к internal


        }


    }


}


Код:



package containers {


 


    // Класс public доступен везде


    public class Bowl {


       


        // Переменная public доступна везде


        public var pubNum:Number = 1;


       


        // protected – доступ только у наших потомков


        protected var protNum:Number = 2;


       


        // private – доступ только в этом классе


        private var privNum:Number = 3;


       


        // internal – доступ только в этом пакете (package)


        internal var interNum:Number = 4;


           


        // Конструктор всегда public


        function Bowl() {


           


            // Есть доступ к inteneral т.к. в этом же пакете


            var basket:Basket = new Basket();


           


            trace(basket.pubNum); // OK


            // trace(basket.protNum); // Error – нет доступа к protected


            // trace(basket.privNum); // Error - нет доступа к private


            trace(basket.interNum); // OK – в этом же пакете


           


            // clone объявлен как public


            var basketCopy:Basket = basket.clone();


        }


    }


}


Код:



package containers {


   


    // interal – доступ только в этом пакете (package)


    internal class Basket {


       


        // public – доступ отовсюду


        public var pubNum:Number = 1;


       


        // protected – доступ только у потомков


        protected var protNum:Number = 2;


       


        // private – доступ только в этом классе


        private var privNum:Number = 3;


       


        // internal – доступ только в этом пакете (package)


        internal var interNum:Number = 4;


       


        // Конструктор всегда public


        function Basket() {


        }


       


        // public – доступ отовсюду


        public function clone():Basket {


            var basket:Basket = new Basket();


            basket.pubNum = pubNum; // OK


            basket.protNum = protNum; // OK – этот же класс


            basket.privNum = privNum; // OK - этот же класс


            basket.interNum = interNum; // OK


            return basket;


        }


    }


}

(flasher.ru)

воскресенье, 10 августа 2008 г.

Классы в Action Script 3.0.

Классы в Action Script 3.0.
Классы - неотъемлемая часть ActionScript 3.0. Это справедливо для ActionScript 3.0 как ни для одной другой, более ранней версии этого языка. ActionScript 1.0 был преимущественно процедурным языком со скромными объектно-ориентированными возможностями. Action-Script 2.0 формализовал объектно-ориентированные черты и сделал большой шаг по направлению к истинно объектно-ориентированному языку. Однако именно ActionScript 3.0 меняет основной курс Action-Script и делает классы основными строительными блоками языка. Ес¬ли ActionScript 3.0 используется с Flex, то весь код ActionScript дол¬жен находиться в классе, исключение составляет код, размещаемый в тегах .
Как уже говорилось, класс - это основной строительный блок всех приложений на ActionScript 3.0. Поэтому, чтобы создавать приложения, необходимо освоить азы написания классов. Для начинающих заметим, что все классы должны размещаться в обычных текстовых файлах, имеющих расширение .as. В одном файле может, располагается только одно описание открытого класса. Имена файла и класса должны быть одинаковыми. Например, если имя класса Example, тогда его описание должно храниться в файле под названием Example.as. В ActionScript 3.0 все классы должны размещаться в пакетах.
Пакет - это средство организации классов в группы. В ActionScript 3.0 пакет тождествен каталогу файловой системы. Пакеты соответствуют пути к классу, но в этом вводн. обсуждении будем считать, что путь к классу - это и путь к проекту (файлу .fla в случае Flash, основному классу или документу MXML в случае Flex). Следовательно, пакет верхнего уровня аналогичен корню проекта. Описание пакета всегда стоит самым первым в файле класса. Вот пример синтаксиса:
package имя {

}
Когда класс определяется как часть пакета верхнего уровня, имя пакета задавать не надо. В этих случаях описание пакета имеет следующий вид:
package {
}
Когда файл класса сохраняется в подкаталоге, имя пакета соответствует относительному пути подкаталога (имена каталогов разделяют точками (.)). Например, если файл сохраняется в подкаталог (относительно корня проекта) example, описание пакета имеет вид:
package example {

}

Если файл класса сохраняется в подкаталоге example под именем subpackage (подпакет), описание пакета будет таким:
package example.subpackage {

}
Пакеты являются важной частью работы с классами, потому, что позволяет предотвратить конфликты имен классов. Например два разработчика вполне могут написать два разных класса и назвать MessageManager (Диспетчер Сообщений). Эти два класса могут иметь одинаковые имена, но отвечать за очень разные задачи. Один может управлять сообщениями электронной почты, а другой заниматься передачей двоичных сообщений через сетевые соединения. В одной области видимости не может быть двух классов с одинаковыми именами. Если это происходит, компилятор не знает, какой из классов использовать. Единственный выход — всегда давать классам уникальные имена
В этом примере можно было бы назвать классы EmailManager и BinarySocketMessageManager. Однако есть веские причины, по которым такой подход не всегда возможен или приемлем. Проект потенциально может использовать сотни классов, поэтому очень сложно обеспечит: уникальность имен всех классов. Более того, многие проекты могут задействовать уже существующие библиотеки кода, созданные другими разработчиками. А так как многие классы библиотеки могут быть взаимосвязаны с другими классами, изменение их имен вызвало бы большие сложности. Вот здесь на помощь приходят пакеты. Даже не смотря на то, что в одном каталоге не может быть двух одинаково на званых классов, таких классов может быть сколько угодно, их просто нужно сохранять в разных каталогах. Один класс MessageManager можно поместить в пакет net.messaging.email, а другой MessageManager в пакет net.messaging.binarysocket.
Приведенные имена пакетов на первый взгляд кажутся приемлемыми, однако можно обеспечить более высокую степень их уникальности. Как правило, лучше всего выбирать имя пакета, ориентируясь на его владельца и/или проект. Имена пакетов принято начинать с доменных имен, написанных в обратном порядке. Например, если корпорация Example Corp (examplecorp.com) создает классы ActionScript 3.0 она помещает их все в пакет com.examplecorp. Тогда если другая Example Corp из Великобритании (example corp.co.uk) тоже пишет классы ActionScript 3.0, она может обеспечить уникальность, назвав пакет uk.co.examplecorp.
Данная рекомендация не относится к классам, составляющим продукт или библиотеку, область действия которых шире, чем компания/организация. К примеру, все собственные классы Flash Player располагаются в пакете Flash (например, flash.net. URLRequest) и все классы библиотеки «Сборника рецептов Ac¬tionScript 3.0* находятся в пакете ascb (смотрите http://www. rishtactionscript.com/ascb).
Если классы представляют собой часть стандартной библиотеки, за¬действованной в нескольких проектах в пределах компании/организа¬ции, то их можно поместить в подпакеты основного пакета. Так, если вышеупомянутые классы MessageManager - это часть стандартной библиотеки, используемой многими приложениями Example Corp, то они могут размещаться в пакетах com.examplecorp.net.messaging.email и com.examplecorp.net.messaging, binarysocket. Если класс представля¬ет собой часть конкретного приложения, то он должен находиться в специальном подпакете этого приложения. Например, у Example Corp может быть приложение WldgetStore. Если приложение WldgetStore использует класс ApplicationManager, то он должен быть помещен в пакет com.examplecorp.widgetstore или его подпакет.
Имена пакетов начинаются со строчной буквы.
Следующий шаг - объявить сам класс:
public class Имя {

}

В соответствии с соглашением об именовании имя класса начинается с прописной буквы. Имя класса должно подчиняться тем же правилу именования, что и переменные, и функции (состоят из букв, цифр и символов подчеркивания, не могут начинаться с цифры). Описание класса располагается в описании пакета. Следующий код, описывает класс Example в рамках пакета верхнего уровня:
package {
public class Example {
}
}

Тело класса в описании класса заключено в фигурные скобки. Оно стоит из свойств и методов. Свойства - это переменные, ассоциированные с классом. Они объявляются во многом так же, как переменные с помощью ключевого слова var. Однако для свойств должны быть определены еще и атрибуты, определяющие их область видимости. Вот список атрибутов, которые могут использоваться со свойствами: Закрытые (private) свойства доступны только внутри класса.
Открытые (public) свойства доступны как в классе, так и в экземплярах класса (или по прямой ссылке на класс, когда объявлены статические (static)).
Защищенные (protected) свойства доступны только в классе и под классах.
Внутренние (internal) свойства доступны в рамках пакета.
По умолчанию, если не задан другой атрибут, все свойства объявляются как (internal). В большинстве случаев свойства должны объявляться с идентификаторами private или protected. Имена закрытых и защищенных свойств полезно начинать с символа подчеркивания (_). В следующем примере объявляется новое закрытое свойство _id класса Example:
package {
public class Example {
private var _id:String;
}
}

Методы - это функции, ассоциированные с классом. Они объявляются практически так же, как функции, с ключевым словом function. Одна¬ко, как и свойства, все методы должны принадлежать пространству имен, определенному одним из атрибутов из приведенного выше спи¬ска. Атрибуты public, private, protected и internal для методов и свойств имеют одинаковое действие. Методы должны объявляться с модифи¬катором public, если предполагается вызывать их из экземпляров класса (или из самого класса, если он объявлен static). Если метод бу-дет вызываться только из класса, он должен быть объявлен с модифи¬катором private или protected. Метод должен быть защищенным, если необходима возможность ссылаться на него из подкласса. В следую¬щем фрагменте кода объявляется метод getld():
package {
public class Example {
private var _id:String;
public function getld():String {
return _id;
}
}
}

Имена методов подчиняются тем же правилам, что и имена переменных и свойств. Это означает, что имена методов должны содержать только цифры, буквы, символы подчеркивания и знак доллара. Кроме того, не¬смотря на возможность включать цифры, начинаться с цифры имя ме¬тода не может. Имена методов принято начинать со строчных букв. Од¬нако есть одно исключение. В каждом классе может быть особый метод, имя которого аналогично имени класса. Этот особый метод называется конструктором и, как следует из названия, он служит для создания новых экземпляров класса. В ActionScript 3.0 все конструкторы долж¬ны быть открытыми (public, и в этом отличие от ActionScript 2.0).
В от¬личие от стандартных методов, конструкторы не могут возвращать значения и не должны объявлять возвращаемый тип. В следующем Фрагменте кода объявляется метод-конструктор класса Example:
package {
public class Example {
private var _id:String;
public function Example() {
_id = "Example Class";
}
}

}

public function getld():String {
}
Ниже показано создание экземпляра класса Example:
var example:Example = new Example();
trace(example.getld()); //На экран выводится: Example Class