Март 2011

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

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

function Employee (age, salary) { // Описываем динамические переменные экземпляра this. age = age: this. salary = salary;

}

// Передаем аргументы, которые будут использованы в качестве значений // динамических переменных экземпляра данного объекта var worker = new Employee(25, 27000); trace(worker. age); // Выводит: 25

Чтобы объекты, создаваемые с помощью определенной функции-конструктора, могли разделять между собой информацию и поведение, язык ActionScript для каждой функции вводит специальную статическую переменную prototype. Переменная функции prototype ссылается на объект (называемый объектом-прототипом функции), к динамическим переменным экземпляра которого можно обращаться через любой объект, созданный с помощью данной функции. Изначально язык ActionScript присваивает переменной prototype каждой функции экземпляр базового класса Object. Добавляя в этот объект динамические переменные экземпляра, мы можем создать информацию и поведение, разделяемые между всеми объектами, созданными из конкретной функции.

Например, следующий код добавляет динамическую переменную экземпляра company в объект prototype функции Employee ( ):

Employee. prototype. company = «AnyCorp»;

В результате любой объект, созданный из функции Employee ( ), может обращаться к переменной company так, будто это его собственная динамическая переменная экземпляра:

var worker = new Employee(25, 27000); trace(worker. company); // Выводит: AnyCorp

В предыдущем коде, когда среда выполнения Flash поймет, что объект, созданный из функции Employee ( ) (worker), не имеет переменной экземпляра или метода экземпляра с именем «company», она проверит, определена ли динамическая переменная экземпляра с таким именем в объекте Employee. prototype. В этом объекте такая переменная определена’ поэтому среда Flash использует ее так, будто это собственная переменная объекта worker.

Если, с другой стороны, в объекте worker определена собственная переменная company, она будет использована вместо переменной объекта Employee. prototype. Это демонстрирует следующий код:

var worker = new Employee(25, 27000); worker. company = «CarCompany»;

trace(worker. company); // Выводит: CarCompany (не AnyCorp)

Используя методику, рассмотренную в разд. «Динамическое добавление нового поведения в экземпляр», мы можем присвоить функцию динамической переменной экземпляра объекта prototype любой функции-конструктора. Эта функция в дальнейшем может быть использована любым объектом, созданным из данной функции-конструктора.

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

Например, следующий код определяет динамическую переменную экземпляра getBonus в объекте prototype функции Employee ( ) и присваивает этой переменной функцию, которая подсчитывает и возвращает премию по итогам года:

Employee. prototype. getBonus = function (percentage:int).-Number { // Возвращает размер премии в зависимости от зарплаты сотрудника // и указанного процента return this. salary * (percentage/100);

}

В результате все объекты, созданные из функции Employee ( ), могут использовать функцию getBonus ( ) так, будто она была присвоена их собственным динамическим переменным экземпляра:

var worker = new Employee(25, 27000); trace(worker. getBonusdO)); // Выводит: 2700

Использование объектов-прототипов для дополнения классов

Как уже было сказано, язык ActionScript определяет для каждой функции специальную статическую переменную prototype. Используя переменную prototype функции, мы можем разделять информацию и поведение между всеми объектами, созданными из этой функции.

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

Например, следующий код определяет новую динамическую переменную экземпляра isEmpty в объекте prototype внутреннего класса String и присваивает ей функцию. Эта функция возвращает значение true, когда строка не содержит символов; в противном случае функция возвращает значение false:

String. prototype. isEmpty = function ( ) { return (this == «») ? true : false;

}:

Для вызова функции isEmpty ( ) над объектом String мы используем следующий код:

var si:Stri ng = «Hello World»; var s2:String = «»;

trace(sl. isEmpty( )); // Выводит: false trace(s2.isEmpty( )); // Выводит: true

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

Call to a possibly undefined method isEmpty through a reference with static type String.

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

Яо-русски она будет звучать так: Вызов возможно неопределенного метода isEmpty через ссылку на статический тип String.

Чтобы обращение к функции isEmpty ( ) при использовании строгого режима не приводило к ошибке на этапе компиляции, мы должны применять динамическое обращение, как показано в следующем коде:

sl["isEmpty"]( )

С другой стороны, если бы класс String не был объявлен с использованием атрибута dynamic, первоначальный подход (то есть si. isEmpty ( ) ) не вызывал бы ошибку.

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

Цепочка прототипов

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

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

// Создаем простейший класс А dynamic public class А {

}

// Создаем другой простейший класс В, который расширяет класс А

dynamic public class В extends А {

}

// Создаем основной класс приложения public class Main extends Sprite { public function Main ( ) {

// Добавляем динамическую переменную экземпляра в объект-прототип

// класса А

A. prototype. day = «Monday»;

// Обращаемся к переменной A. prototype. day через экземпляр класса В

var b:B = new В( );

trace(b. day); // Выводит: «Monday»

}

}

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

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

Рассмотрим, как работают цепочки прототипов. Предположим, что мы создаем функцию Employee ( ), как делали это раньше, в объекте-прототипе которой определяем динамическую переменную экземпляра company:

function Employee ( ) { } •

Employee. prototype. company = «AnyCorp»;

Любой объект, созданный из функции Employee ( ), может обращаться к переменной company через объект-прототип функции Empoyee ( ). Ничего нового. Теперь предположим, что мы создали еще одну функцию Manager ( ):

function Manager ( ) { }

Предположим также, что необходимо сделать так, чтобы объекты, созданные из функции Manager ( ), могли обращаться к переменной company через объект-прототип функции Employee ( ). Для этого мы присваиваем объект, созданный из функции Employee ( ), переменной prototype функции Manager ( ).

Manager. prototype = new Employee( );

Теперь рассмотрим, что произойдет, если мы обратимся к переменной с именем » company» через объект, созданный из функции Manager ( ), как показано в следующем коде:

var worker = new Manager( ); trace(worker. company);

При выполнении предыдущего кода среда Flash проверяет, имеет ли объект worker переменную или метод экземпляра с именем » company». Объект worker не имеет

переменной или метода экземпляра с таким именем, поэтому далее среда выполнения Flash проверяет, определена ли динамическая переменная экземпляра с именем «company» в объекте-прототипе функции Manager ( ). Сам по себе объект-прототип функции Manager ( ) является объектом, созданным из функции Employee ( ). Тем не менее в объектах, созданных из функции Employee ( ), динамическая переменная экземпляра с именем «company» не определена. Следовательно, после этого среда Flash проверяет, определена ли динамическая переменная экземпляра с именем » company» в объекте-прототипе функции Employee ( ). В нем такая переменная определена, поэтому среда выполнения Flash использует ее так, будто это собственная переменная объекта worker.

Рассмотрим путь, который проходит среда Flash при поиске переменной с именем «company».

1. Ищем переменную company в объекте worker. Не найдена.

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

2. Ищем переменную company в объекте Manager. prototype. Не найдена.

3. Объект Manager. prototype создан из функции Employee ( ), поэтому ищем переменную company в объекте Employee. prototype. Найдена!

Список объектов-прототипов, просматриваемых средой выполнения Flash при попытке определить значение переменной, называется цепочкой прототипов. До появления языка ActionScript 3.0 цепочка прототипов была основным механизмом для разделения повторно используемого поведения между различными типами объектов. В языке ActionScript 3.0 эту роль играет наследование классов.

Обратите внимание на следующие ограничения, налагаемые на цепочки прототипов в ActionScript 3.0.

? Объект, присваиваемый переменной prototype функции, сам по себе должен являться объектом, созданным из функции, или экземпляром класса Object (использование экземпляров других классов не допускается).

? Значение переменной prototype класса присваивается средой выполнения Flash автоматически и в дальнейшем не может быть изменено.

Вперед!

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

ГЛАВА 18

Область видимости

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

? тело функции;

? тело метода экземпляра;

? тело статического метода;

? тело класса;

? все остальное (то есть глобальная область видимости).

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

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

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

public class SomeClass { public function someMethod ( ):void { function someNestedFunction ( ):void { // Область видимости данной функции вложена внутрь области видимости // метода someMethod( ). которая вложена в область видимости класса // SomeClass

}

}

}

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

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

Обратите внимание, что помимо «доступных» определений, перечисленных в каждом из последующих разделов, определения, объявленные во внешнем пакете с использованием модификатора управления доступом public, можно сделать видимыми и в данной области видимости с помощью директивы import. Подробную информацию можно найти в подразд. «Пример создания объекта: добавление животного в зоопарк» разд. «Создание объектов» гл. 1.

Местоположение определения и используемые при его объявлении модификаторы управления доступом совместно определяют доступность данного определения в программе. Для информации в табл. 16.1 приведена доступность определений в соответствии с их местоположением и применяемым модификатором управления доступом.

Таблица 16.1. Доступность определения в зависимости от его местоположения и используемого модификатора управления доступом

Определение Доступно

Определение за пределами всех пакетов Только внутри исходного файла, содержащего данное определение

Определение в безымянном пакете В любой точке программы

Определение с использованием модификатора управления доступом public в именованном пакете Внутри пакета, содержащего данное определение, и в любом месте, где оно импортируется

Определение с использованием модификатора управления доступом internal в именованном пакете Только внутри пакета, содержащего данное определение

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

Метод или переменная, объявленные с использованием модификатора управления доступом internal Внутри пакета, содержащего класс с данным определением

Метод или переменная, объявленные с использованием модификатора управления доступом protected Внутри класса, содержащего данное определение, и его классов-потомков

Метод или переменная, объявленные с использованием модификатора управления доступом private Только внутри класса, содержащего данное определение

Определение в методе экземпляра, статическом методе или функции Доступно внутри метода или функции, содержащих данное определение, а также во всех вложенных в них функциях

Глобальная область видимости

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

package {

// Этот код находится в глобальной области видимости

}

// Этот код также находится в глобальной области видимости

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

? на верхнем уровне безымянного пакета;

? за пределами всех пакетов, но в том же исходном файле (AS).

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

Другими словами:

package {

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

}

// Размещенные здесь определения доступны всему коду в том же исходном файле

Стоит отметить, что код, размещенный на верхнем уровне тела именованного пакета, может также обращаться к определениям, размещенным на верхнем уровне того же пакета. Эти определения доступны потому, что внутри именованного пакета язык ActionScript автоматически открывает пространство имен, связанное с данным пакетом (более подробную информацию можно найти в гл. 17). Иными словами:

package somePackage { // Размещенные здесь определения становятся автоматически доступны // всему коду в пакете somePackage

}

Область видимости класса

Код, помещенный на верхний уровень тела класса, находится в области видимости этого класса. Например:

package { public class SomeClass { // Размещенный здесь код находится в области видимости класса someClass

}

}

Помните, что код, размещенный на верхнем уровне тела класса, включается в автоматически создаваемый статический метод (инициализатор класса), который выполняется всякий раз, когда среда Flash определяет класс на этапе выполнения программы. Подробную информацию можно найти в разд. «Статические методы» гл. 4.

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

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

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

? статическим методам и статическим переменным, определенным в этом классе;

? статическим методам и статическим переменным, определенным в предках данного класса, если они существуют (то есть в суперклассе, суперклассе суперкласса и т. д.).

Иначе говоря:

package {

public class SomeClass extends SomeParentClass { // Определенные здесь статические переменные // и статические методы доступны // в любом месте класса SomeClass

}

}

package { public class SomeParentClass { // Определенные здесь статические переменные // и статические методы доступны // в любом месте класса SomeClass

}

}

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

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

Область видимости статического метода

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

package { public class SomeClass { public static function staticMeth ( ) { // Размещенный здесь код находится в области видимости метода // staticMeth

}

}

}

Через цепочку областей видимости код в области видимости статического метода может обращаться к этим определениям:

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

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

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

Другими словами:

package {

public class SomeClass extends SomeParentClass { public static function staticMeth ( ) { // Определенные здесь локальные переменные, вложенные функции

Область видимости функции

349

// и пространства имен доступны в методе staticMeth

}

}

}

Область видимости метода экземпляра

Код, помещенный в тело метода экземпляра, находится в области видимости данного метода:

package { public class SomeClass { public function instanceMeth ( ) { // Размещенный здесь код находится в области видимости // метода instanceMeth

}

}

}

Через цепочку областей видимости код в области видимости метода экземпляра может обращаться к следующим определениям:

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

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

? ко всем методам и переменным экземпляра объекта, через который был вызван данный метод экземпляра (с учетом ограничений, налагаемых используемыми модификаторами управления доступом);

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

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

Это демонстрирует следующий код:

package {

public class SomeClass extends SomeParentClass { public function instanceMeth ( ) { // Все методы и переменные экземпляра текущего объекта (то есть this) // доступны в методе instanceMeth( ) (с учетом ограничений, налагаемых // используемыми модификаторами управления доступом). // Определенные здесь локальные переменные, вложенные функции // и пространства имен доступны в методе instanceMeth( )

}

}

}

Область видимости функции

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

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

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

? ко всем локальным переменным, вложенным функциям и пространствам имен, определенным внутри этой функции.

Код в функции, которая определена внутри статического метода, может обращаться к таким определениям:

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

? ко всем определениям, доступным коду в области видимости данного статического метода;

? ко всем локальным переменным, вложенным функциям и пространствам имен, определенным внутри этой функции.



Полезные ссылки
Случайные записи
  • 09.03.2011">Руководство по actionscript. часть 4, стр. 058
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.73
  • 05.11.2011">Как сделать кнопку для сайта
  • 20.02.2011">Как сделать дождь в Adobe Photoshop?
  • 16.03.2011">Руководство по actionscript. часть 3, стр. 010
  • 11.03.2011">Руководство по actionscript. часть 4, стр. 006
  • 22.03.2011">Руководство по actionscript. часть 2, стр. 016
  • 19.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.32
  • 27.02.2011">Руководство по actionscript. часть 6, стр. 035
  • 28.02.2011">Руководство по actionscript. часть 6, стр. 005
  • 06.03.2011">Руководство по actionscript. часть 4, стр. 150
  • 09.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.133
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 141
  • 11.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.10
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 073
Опрос

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

View Results

Loading ... Loading ...