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

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

Типы данных и аннотации типов

В языке ActionScript термин «тип данных» означает просто «набор значений». Язык ActionScript определяет три фундаментальных типа данных: Null, void и Object. Каждый из типов данных Null и void включает по одному значению — null и undefined соответственно (значения null и undefined рассматриваются далее в разд. «Значения null и undefined»). Тип данных Ob j ect включает все экземпляры всех классов.

Кроме трех фундаментальных типов данных (Null, void и Object), любой внутренний или пользовательский класс формирует уникальный тип данных, набором значений которого являются непосредственные экземпляры данного класса и экземпляры его классов-потомков. Например, класс Food из нашей программы по созданию виртуального зоопарка формирует тип данных, набором значений которого являются все экземпляры класса Food и все экземпляры классов Apple и Sushi (поскольку оба класса Apple и Sushi унаследованы от класса Food). Таким образом, говорят, что экземпляры классов Apple и Sushi принадлежат типу данных Food.

Однако каждый из классов Apple и Sushi также формирует собственный тип данных. Например, набором значений типа данных Apple являются все экземпляры класса Apple и все экземпляры любого класса, унаследованного от него. Подобным образом набором значений типа данных Sushi являются все экземпляры класса Sushi и все экземпляры любого класса, унаследованного от него. По этой причине помимо того, что экземпляр класса Apple принадлежит типу данных Food, он также принадлежит типу данных Apple. Однако экземпляр класса Apple не принадлежит типу данных Sushi, поскольку класс Sushi не унаследован от Apple. Точно так же экземпляр класса Sushi принадлежит типам данных Food и Sushi, но не принадлежит тип у данных Apple, поскольку класс Sushi не унаследован от Apple. Наконец, несмотря на то, что экземпляры обоих классов принадлежат типу данных Food, экземпляр класса Food не принадлежит ни одному из типов данных Apple или Sushi, поскольку класс Food не унаследован от классов Apple или Sushi.

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

^ I Обратите внимание на важное различие между отдельно взятым классом и типом данных, м? J „ представляемым этим классом. Набором значений, принадлежащим данному классу, являют— Щ1 ся только экземпляры этого класса. Однако набором значений, принадлежащим типу данных этого класса, являются экземпляры данного класса и экземпляры его классов-потомков.

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

Если у нас есть два типа данных — А и В, причем класс (или интерфейс), представленный типом данных В, унаследован от класса (или интерфейса), представленного типом данных А, то А называется супертипом для В. И наоборот, тип данных В называется подтипом А. Например, тип данных Food является супертипом для Apple, в то время как Apple является подтипом Food.

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

Совместимые типы

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

Обратное, однако, неверно. Класс не может использовать никакие члены экземпляра, определенные в его классах-потомках. Таким образом, любой отдельно взятый супертип считается несовместимым с любым из своих подтипов. Например, тип данных Food считается несовместимым с типом данных Apple, поскольку Food не является подтипом Apple.

Подтип считается совместимым с супертипом, поскольку программа может рассматривать экземпляр подтипа как экземпляр супертипа. Например, программа может рассматривать любой экземпляр типа данных Apple как экземпляр типа данных Food — возможно, вызывая метод getCalories ( ) класса Food над данным экземпляром.

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

// Создаем новый экземпляр класса Apple var apple = new Apple( );

// Допустимо вызвать метод getCaloriesC ) над экземпляром класса Apple apple. getCalories( );

Для сравнения отметим, что супертип считается несовместимым с подтипом, поскольку программа не может рассматривать экземпляр супертипа как экземпляр подтипа. Например, программа не может вызвать метод hasWorm ( ) классаАрр1е над экземпляром типа данных Food:

// Создаем новый экземпляр класса Food var food = new Food(200);

// Следующая строка приведет к возникновению ошибки обращения. // поскольку класс Food не имеет доступа к методу hasWorm( ) food. hasWorm( ); // Ошибка!

Выявление ошибок несоответствия типов с помощью аннотаций типов

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

: тип

Например, определение переменной с использованием аннотации типа имеет следующий обобщенный вид:

var идентификатор \тип = значение;

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

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

function идентификатор (параметр:типПараметра) -.типВозвращаемогоЗначения {

)

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

? имя класса или интерфейса (представляющего тип данных);

? специальный символ * (обозначающий «нетипизированные» данные).

Тип типВозвращаемогоЗначения должен быть одним из следующих:

? имя класса или интерфейса (представляющего тип данных);

? специальный символ * (обозначающий «нетипизированные» данные);

? специальная, «не возвращающая значение», аннотация типа void (которая обозначает, что функция не имеет возвращаемого значения).

Л_

Программисты на языке ActionScript 2.0 должны обратить внимание, что в языке ActionScript 3.0 ключевое слово Void больше не записывается с прописной буквы.

Ш

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

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

Если значение не принадлежит указанному типу данных, то при использовании строгого режима компилятор сгенерирует ошибку (называемую ошибкой несоответствия типов) и прекратит компиляцию кода. При использовании стандартного режима код будет скомпилирован и среда Flash попытается преобразовать значение в указанный тип данных на этапе выполнения программы. Если указанным типом данных является один из внутренних классов String, Boolean, Number, int или uint (называемых примитивными типами), преобразование будет выполнено в соответствии с правилами, описанными в разд. «Преобразование в примитивные типы» этой главы. В противном случае преобразование завершится неудачей и среда Flash сгенерирует ошибку несоответствия типов на этапе выполнения программы. На формальном языке автоматическое преобразование значения на этапе выполнения программы называется приведением.

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

Например, следующий код определяет переменную meal типа Food и присваивает этой переменной экземпляр класса Apple:

var meal:Food = new Apple( ):

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

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

var meal-.Food = new Vi rtual Pet( «Lucky»):

При использовании строгого режима компиляции указанный код приведет к ошибке несоответствия типов, поскольку экземпляры класса VirtualPet не принадлежат типу данных Food. По этой причине компиляция кода прекратится.

При использовании стандартного режима указанный код будет успешно откомпилирован. Тем не менее, поскольку значение (экземпляр класса VirtualPet) не принадлежит типу данных переменной (Food), среда выполнения Flash попытается привести (то есть преобразовать) значение к типу данных переменной на этапе выполнения программы. В данном случае тип данных переменной не является одним из примитивных типов, поэтому преобразование завершится неудачей и среда Flash сгенерирует ошибку несоответствия типов на этапе выполнения программы.

Рассмотрим другой пример. Следующий код определяет переменную pet Hunger типа int и присваивает этой переменной экземпляр класса VirtualPet:

var pet:Virtual Pet = new VirtualPet(«Lucky»); var petHunger:int = pet:

При компиляции указанного кода с использованием строгого режима произойдет ошибка несоответствия типов, поскольку экземпляры класса VirtualPet не принадлежат типу данных int. По этой причине компиляция кода прекратится.

При использовании стандартного режима указанный код будет скомпилирован успешно. Тем не менее, поскольку значение (экземпляр класса VirtualPet) не принадлежит типу данных переменной (int), среда Flash попытается преобразовать значение в тип данных переменной на этапе выполнения программы. В данном слу-

чае тип данных переменной является одним из примитивных типов, поэтому преобразование будет выполнено в соответствии с правилами, описанными в разд. «Преобразование к примитивным типам» этой главы. Таким образом, после выполнения указанного кода значением переменной petHunger будет являться 0.

Разумеется, предыдущий код наверняка разрабатывался не для того, чтобы переменной petHunger присвоить значение 0. Скорее программист просто забыл вызвать метод getHunger ( ) над экземпляром класса VirtualPet, как показано в следующем коде:

var pet-.Virtual Pet = new Vi rtual Pet( «Lucky»); var petHunger:int = pet. getHunger( );

В строгом режиме компилятор честно предупредит нас о проблеме, а в стандартном режиме — нет, предположив, что, поскольку типом данных переменной petHunger является int, мы хотим преобразовать объект VirtualPet в тип int. В нашем случае это предположение оказалось неверным, в результате чего программа получила неожидаемое значение.

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

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

^ I В оставшейся части книги мы будем полагать, что весь код компилируется в строгом м? л п Режиме и Для всех переменных, параметров и возвращаемых значений указываются — Tfey аннотации типа.

Нетипизированные переменные, параметры, возвращаемые значения и выражения

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

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

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

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

var stuff = true:

stuff = new VirtualPetC’Edwin»); // Ошибки нет

I Компилятор языка ActionScript не генерирует ошибки несоответствия типов для нетипи-м$ j „ зированных переменных, параметров и возвращаемых значений.

ipj_

Если программист хочет явно указать, что переменная, параметр или возвращаемое значение намеренно являются нетипизированными, он может использовать специальную аннотацию типа : *. Например, следующий код определяет явно не-типизированную переменную totalCost:

var totalCost:* = 9.99:

Следующий код определяет ту же переменную, но на этот раз она является нетипизированной неявно:

var totalCost =9.99;

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

Три особых случая строгого режима

Существует три ситуации, в которых компилятор игнорирует ошибки несоответствия типов при компиляции программы в строгом режиме, не позволяя выявить возможные ошибки до этапа выполнения:

? когда нетипизированное выражение присваивается типизированной переменной или параметру либо возвращается из функции с объявленным типом возвращаемого значения;

? если любое выражение присваивается типизированной переменной или параметру, чьим объявленным типом является Boolean, либо возвращается из функции, объявленным типом возвращаемого значения которой является Boolean;

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

Рассмотрим каждый из описанных случаев на примере. Сначала создадим нети-пизированную переменную pet и присвоим ее значение типизированной переменной <±

var pet:* = new Vi rtualPet(«Francis»): pet = new Date( ); var d:Date = pet;

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

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

Теперь рассмотрим следующий код, в котором определяется переменная b типа Boolean и этой переменной присваивается целочисленное значение 5:

var b:Boolean = 5;

Даже несмотря на то, что значение 5 не принадлежит типу данных Boolean, компилятор не генерирует ошибку несоответствия типов. Вместо этого он делает предположение, что программист желает привести значение 5 к типу данных Boolean (в соответствии с правилами, описанными в разд. «Преобразование в примитивные типы») и генерирует соответствующее предупреждение. Такая «мягкость» компилятора позволяет сократить количество кода в программе. Например, предположим, что в качестве типа возвращаемого значения метода getHunger ( ) класса VirtualPet указан тип данных Number. Программа может создать переменную, содержащую информацию о том, является животное живым или мертвым, используя следующий код:

var isAlive:Boolean = somePet. getHunger( );

В соответствии с правилами, описанными в разд. «Преобразование в примитивные типы», число 0 преобразуется в значение false, а остальные числа — в значение true. Таким образом, если метод getHunger ( ) возвращает любое значение, отличное от 0, переменной is Alive присваивается значение true; в противном случае переменной is Alive присваивается значение false (животное оказывается мертвым, когда у него не остается калорий).

Для сравнения приведем альтернативный, чуть более длинный код, который пришлось бы использовать в том случае, если бы компилятор проверял типы для переменных типа Boolean (не позволяя преобразовывать их на этапе выполнения программы):

var isAlive:Boolean = somePet. getHunger( ) > 0;

Наконец, рассмотрим код, в котором определяется переменная xCoordinate типа int и этой переменной присваивается значение 4, 6459 типа Number:

var xCoordinate:int = 4.6459;

Даже несмотря на то, что значение 4, 64 5 9 не принадлежит типу данных int, компилятор не генерирует ошибку несоответствия типов. Вместо этого он делает предположение, что вы желаете преобразовать значение 4, б 4 5 9 к типу данных int (в соответствии с правилами, описанными в разд. «Преобразование в примитивные типы»). Это позволяет максимально упростить взаимодействие между числовыми типами данных языка ActionScript.

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

Предупреждения об отсутствующих аннотациях типов

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

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

К счастью, компиляторы языка ActionScript компании Adobe предлагают режим предупреждений, при использовании которого на этапе компиляции сообщается обо всех отсутствующих аннотациях типов. Разработчики могут использовать эти предупреждения для поиска случайно пропущенных аннотаций типов. В приложении Flex Builder и компиляторе mxmlc предупреждения об отсутствующих аннотациях типов включены по умолчанию. В среде разработки Flash предупреждения об отсутствующих типах должны быть включены вручную, для чего используется такая последовательность действий.

1. Используя любой текстовый редактор, откройте файл EnabledWarnings. xml, находящийся в папке /en/Configuration/ActionScript 3.0, которая расположена внутри папки приложения Flash CS3.

2. Найдите следующие строки:

Missing type declaration.

3. Измените enabled=»f alse» на enabled=fftrue».

4. Сохраните файл EnabledWarnings. xml.

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

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

Выявление ошибок обращения на этапе компиляции

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

Например, в следующем коде создается переменная pet типа VirtualPet и этой переменной присваивается экземпляр класса VirtualPet:

var pet:Virtual Pet = new VirtualPet(«Stan»);

Затем в следующем коде происходит попытка обращения к несуществующему методу eatt ( ) через типизированную переменную pet:

pet. eatt(new Sushi( ));

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

1061: Call to a possibly undefined method eatt through a reference with static type zoo-.Virtual Pet.

На русском языке текст ошибки будет следующим: Вызов, вероятно, неопределенного метода eatt через ссылку статического типа zoo:VirtualPet.

Однако стоит отметить, что компилятор не сообщает об ошибках обращения, происходящих в нетипизированных выражениях. Более того, обращения к несуществующим переменным и методам через экземпляры динамических классов (таких как Ob j ect) не приводят к генерации вообще никаких ошибок обращения; вместо этого в результате возвращается значение undefined.

Дополнительную информацию о динамических классах можно найти в гл. 15.

I Существует дополнительное преимущество при использовании аннотаций типов: в прило-м$ а п жении Flex Builder и среде разработки Flash аннотации типов для переменных, параметров fly и возвращаемых значений активизируют подсказки кода. Подсказка кода представляет собой удобное всплывающее меню, содержащее список свойств и методов объектов, которые можно добавить в ваш код путем выбора требуемого элемента.



Полезные ссылки
Случайные записи
  • 24.07.2011">Медицинские справки можно получать еще быстрее
  • 02.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.113
  • 23.02.2011">Руководство по actionscript. часть 7, стр. 038
  • 22.03.2011">Руководство по actionscript. часть 2, стр. 008
  • 05.03.2011">Руководство по actionscript. часть 5, стр. 024
  • 16.03.2011">Руководство по actionscript. часть 3, стр. 027
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.83
  • 04.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.25
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.96
  • 22.03.2011">Руководство по actionscript. часть 2, стр. 003
  • 14.03.2011">Руководство по actionscript. часть 3, стр. 077
  • 19.07.2012">На серверах Dropbox произошла утечка адресов e-mail
  • 25.02.2011">Руководство по actionscript. часть 6, стр. 086
  • 17.03.2011">Руководство по actionscript. часть 2, стр. 143
  • 22.03.2011">Руководство по actionscript. часть 2, стр. 010
Опрос

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

View Results

Loading ... Loading ...