Московский физико-технический институт
Опубликован: 23.12.2005 | Доступ: свободный | Студентов: 2868 / 252 | Оценка: 4.61 / 4.44 | Длительность: 27:18:00
ISBN: 978-5-9556-0051-2
Лекция 9:

Классы и клипы

Свойства, свои и чужие объекты

Если объект "свой", то есть мы можем ему завести 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. В нашей функции такая возможность не предусмотрена.