Казахстан, Алматы, Гимназия им. Ахмета Байтурсынова №139, 2008 |
Классы и клипы
Свойства, свои и чужие объекты
Если объект "свой", то есть мы можем ему завести setter -метод, то все достаточно тривиально, и мы это обсуждать не будем.
Допустим, что все обстоит несколько сложнее, а именно: у объекта уже есть поле, которое всеми активно используется, а вам зачем-то очень нужно контролировать его изменение, при этом сам объект "чужой", то есть вы не хотите/не можете изменять его исходный код.
Хорошо было бы иметь функцию, которая позволяет следить за полями в "чужом" объекте. Рассмотрим первый возможный вариант. Напишем функцию watchFunction, которая стирает существующее поле в объекте, сохраняя его значение, создает в объекте вместо него свойство с таким же именем и определяет такие getter и setter, чтобы можно было передать функцию реакции:
function reaction (sender, oldValue, newValue){ //функция реакции trace ("Object: " + sender + ", old value: " + oldValue + ", newValue: " + newValue); return newValue; //нужно вернуть значение, //которое будет присвоено свойству } circle.myField = 5; //исходная переменная в объекте //заводим функцию прямо в Object.prototype, чтобы можно было //вызывать ее для любого объекта. Object.prototype.watchFunction = function (propName, reaction) { var tmpValue = this[propName]; //сохраняем значение delete this[propName]; //удаляем переменную this["get" + propName] = function () { //определяем getter return this["field" + propName]; //"field" + propName - // новое имя переменной }; this["set"+propName] = function (newValue) { //определяем setter this["field" + propName] = reaction(this, this["field" + propName], newValue); // вызываем функцию реакции, возвращенное значение устанавливаем // как новое значение свойства }; //регистрируем новое свойство this.addProperty (propName, this["get"+propName], this["set"+propName]); this["field"+propName] = tmpValue; // восстанавливаем исходное значение } circle.watchFunction ("myField", reaction); //включаем слежение circle.myField = 6; circle.myField = 7;
Теперь, если вы посмотрите на вывод программы, то увидите вот что:
Object: _level0.circle, old value: 5, newValue: 6 Object: _level0.circle, old value: 6, newValue: 7
Если не свойства, то что?
А если нам почему-то не хочется использовать такой способ?
Есть еще один вариант - во Флэш МХ есть функция watch, которая позволяет следить за переменными объекта.
Ее использование выглядит следующим образом: object.watch (propName, reactionFunction, userData), где propName - это имя свойства, за которым нужно следить (строка), reactionFunction - это функция реакции, определение которой должно выглядеть так:
function reactionFunction (propName, oldVal, newVal, userData) { //... return newVal; //здесь возвращается значение, // которое будет в итоге присвоено переменной }
Обратите внимание, что параметр userData - это дополнительные данные, которые могут быть переданы в функцию.
Пример использования стандартной функции watch:
function reaction (sender, oldValue, newValue) { //функция реакции trace ("Object: " + sender + ", old value: " + oldValue + ", newValue: " + newValue); return newValue; //нужно вернуть значение, // которое будет присвоено свойству } circle = {}; circle.myField = 5; //исходная переменная в объекте circle.watch ("myField", reaction); //включаем слежение circle.myField = 6; circle.myField = 7;
Рассмотрим различия в интерфейсе стандартной функции watch и "нашей" функции watchFunction, которую мы рассмотрели в предыдущем примере.
Фактически, их только два:
- во-первых, при использовании стандартной функции watch в callback -метод реакции в качестве первого параметра передается имя поля объекта, за которым производится слежение, а в нашей функции - ссылка на объект.
- во-вторых, в стандартной функции watch есть возможность передать дополнительные данные в функцию реакции через четвертый параметр функции реакции и функции watch. В нашей функции такая возможность не предусмотрена.