Руководство по 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( )
}
}
}
Область видимости функции
Код, добавленный в тело функции, находится в области видимости данной функции. Конкретный список определений, доступных коду, находящемуся в области видимости функции, зависит от местоположения этой функции в программе.
Код в функции, которая определена на уровне пакета или за пределами всех пакетов, может обращаться к следующим определениям:
? ко всем определениям, доступным коду в глобальной области видимости;
? ко всем локальным переменным, вложенным функциям и пространствам имен, определенным внутри этой функции.
Код в функции, которая определена внутри статического метода, может обращаться к таким определениям:
? ко всем определениям, доступным коду в глобальной области видимости;
? ко всем определениям, доступным коду в области видимости данного статического метода;
? ко всем локальным переменным, вложенным функциям и пространствам имен, определенным внутри этой функции.
Руководство по actionscript. часть 2, стр. 130
Код в функции, определенной внутри метода экземпляра, может обращаться к следующим определениям:
? ко всем определениям, доступным коду в глобальной области видимости;
? ко всем определениям, доступным коду в области видимости данного метода экземпляра;
? ко всем локальным переменным, вложенным функциям и пространствам имен, определенным внутри этой функции.
Код в функции, которая определена внутри другой функции, может обращаться к таким определениям:
? ко всем определениям, доступным коду в глобальной области видимости;
? ко всем определениям, доступным коду в области видимости внешней функции;
? ко всем локальным переменным, вложенным функциям и пространствам имен, определенным внутри этой функции.
Обзор областей видимости
Приведенный далее код демонстрирует все возможные области видимости языка ActionScript:
package {
// Размещенный здесь код находится в глобальной области видимости
public class SomeClass { // Этот код находится в области видимости класса SomeClass
public static function staticMeth ( ):void { // Размещенный здесь код находится в области видимости метода // staticMeth
}
public function instanceMeth ( ):void { // Этот код находится в области видимости метода instanceMeth
function nestedFunc ( ):void { // Размещенный здесь код находится в области видимости функции // nestedFunc
}
}
}
}
// Этот код находится в глобальной области видимости
Детали реализации
Для осуществления хранения информации об определениях в цепочке областей видимости среда Flash использует список объектов. Информацию об определениях для каждой области видимости хранят следующие объекты.
Руководство по actionscript. часть 2, стр. 131
Глобальная область видимости — глобальный объект (объект, автоматически создаваемый средой выполнения Flash для хранения глобальных определений).
Область видимости класса — объект Class данного класса (и объекты Class его предков).
Область видимости статического метода — объект Class данного класса (и объекты Class его предков).
Область видимости метода экземпляра — текущий объект (this) и объект активации (объект активации — это объект, создаваемый средой выполнения Flash и хранящийся в ней, который включает локальные переменные и параметры функции или метода).
Область видимости функции — объект активации.
Когда среда выполнения Flash встречает в программе выражение-идентификатор, она выполняет поиск этого идентификатора среди объектов в цепочке областей видимости. Например, рассмотрим следующий код:
package { public class SomeClass { public function instanceMeth ( ):void { function nestedFunc ( ):void { trace(a):
}
}
}
}
var a.-int = 15;
Когда среда Flash встречает идентификатор а, она выполняет поиск его значения в объекте активации функции nestedFunc ( ). Однако в функции nestedFunc ( ) не определено никаких локальных переменных или параметров с именем а, поэтому далее среда Flash продолжает поиск идентификатора а в текущем объекте (то есть в объекте, через который был вызван метод instanceMeth ( ) ). Но класс SomeClass не определяет и не наследует метод или переменную экземпляра
с именем а, поэтому после этого Flash продолжает поиск идентификатора а в классе объекта SomeClass. В классе SomeClass отсутствует определение статического метода или статической переменной с именем а, поэтому далее среда выполнения Flash продолжает поиск идентификатора а в объекте суперкласса класса SomeClass, которым является класс Ob j ect. Однако в классе Ob j ect отсутствует определение статического метода или статической переменной с именем а, поэтому после этого среда Flash продолжает поиск идентификатора а в глобальном объекте. В нем Flash находит идентификатор а и определяет, что значением этого идентификатора является 15. Получив значение идентификатора а, среда выполнения выводит число 15 в процессе отладки. Довольно много действий, чтобы найти маленькую а!
Вот объекты, среди которых среда выполнения Flash пыталась найти идентификатор а, перечисленные в порядке поиска:
? объект активации функции nestedFunc ( );
? объект, через который был вызван метод instanceMeth ( );
? объект класса SomeClass;
? объект класса Object;
? глобальный объект.