Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 29.11.2010, 18:21
Aquahawk вне форума Посмотреть профиль Отправить личное сообщение для Aquahawk Посетить домашнюю страницу Aquahawk Найти все сообщения от Aquahawk
  № 1  
Ответить с цитированием
Aquahawk
 
Аватар для Aquahawk

Регистрация: Nov 2010
Адрес: Москва
Сообщений: 915
Записей в блоге: 4
Отправить сообщение для Aquahawk с помощью ICQ Отправить сообщение для Aquahawk с помощью Skype™
По умолчанию сохранение и последующий вызов функции.

Начну с того что пишу на flash платформе недавно, ранее 5 лет писал на C/C++ там такого нельзя делать было в принципе, а в as3 можно, но я не до конца понимаю механизм. Что происходит когда мы запоминаем метод объекта? Прочитал вики по ECMAScript и хелп эдоба на эту тему. Стало понятно что функция сама является объектом, и где-то внутри хранит "владельца" т.е. того объекта для которого её вызвали. Т.е. когда мы делаем:
Код AS3:
var qqq:Function = test1.a1;
var www:Function = test2.a1;
то получаем два разных экземпляра функций которые обрабатывают разный объект(test1 и test2 соответственно). Указатель на this хранится где-то внутри этого объекта функции? Также эдоб говорит что этим this можно управлять при вызове функции посредством call() и apply(), однако у мня не получилось, может кто пояснить почему так происходит? Внутри вызываемых функций прописывать this.a += пробовал, ничего не меняется. Варнингов/ошибок нет, функция всё-равно отрабатывает для того объекта от которого была взята.
Код AS3:
package test {
	import flash.display.Sprite;
	public class abra extends Sprite {
		private var test1:testClass;
		private var test2:testClass;
 
		public function abra():void {
			test1 = new testClass();
			test2 = new testClass();
 
			var qqq:Function = test1.a1;
			var www:Function = test2.a1;
			var qwe:Function = test2.a2;
 
			trace("test1.a = " + test1.a + "; test2.a = " + test2.a);
			qqq();
			trace("test1.a = " + test1.a + "; test2.a = " + test2.a);
			www();
			trace("test1.a = " + test1.a + "; test2.a = " + test2.a);
			qwe();
			trace("test1.a = " + test1.a + "; test2.a = " + test2.a);
			qqq.call(test2);
			trace("test1.a = " + test1.a + "; test2.a = " + test2.a);
			qqq.apply(test2);
			trace("test1.a = " + test1.a + "; test2.a = " + test2.a);
		}
	}
}
class testClass {
	public var a:uint = 0;
 
	public function testClass() {
	}
 
	public function a1():void {
		a += 1;
	}
	public function a2():void {
		a += 2;
	}
}
результат трейса
Код:
test1.a = 0; test2.a = 0
test1.a = 1; test2.a = 0
test1.a = 1; test2.a = 1
test1.a = 1; test2.a = 3
test1.a = 2; test2.a = 3
test1.a = 3; test2.a = 3
При дизассемблировании(swfdump -D) релизной(релиз чтоб листинг чище был) сборки это выглядит так(позволил себе прокомментировать что сразу понятнее было):
Код AS3:
00000) + 0:0 getlocal_0
00001) + 1:0 pushscope
 
/* super(); */
00002) + 0:1 getlocal_0
00003) + 1:1 constructsuper 0 params
 
/* test1 = new testClass(); */
00004) + 0:1 getlocal_0
00005) + 1:1 findpropstrict <q>[private]NULL::testClass
00006) + 2:1 constructprop <q>[private]NULL::testClass, 0 params
00007) + 2:1 initproperty <q>[private]NULL::test1
 
/* test2 = new testClass(); */
00008) + 0:1 getlocal_0
00009) + 1:1 findpropstrict <q>[private]NULL::testClass
00010) + 2:1 constructprop <q>[private]NULL::testClass, 0 params
00011) + 2:1 initproperty <q>[private]NULL::test2
 
/* var qqq:Function = test1.a1; */
00012) + 0:1 getlocal_0
00013) + 1:1 getproperty <q>[private]NULL::test1
00014) + 1:1 getproperty <q>[public]::a1
00015) + 1:1 coerce <q>[public]::Function 
00016) + 1:1 setlocal_1 
 
/* var www:Function = test2.a1; */
00017) + 0:1 getlocal_0
00018) + 1:1 getproperty <q>[private]NULL::test2
00019) + 1:1 getproperty <q>[public]::a1
00020) + 1:1 coerce <q>[public]::Function
00021) + 1:1 setlocal_2
 
/* var qwe:Function = test2.a2; */
00022) + 0:1 getlocal_0
00023) + 1:1 getproperty <q>[private]NULL::test2
00024) + 1:1 getproperty <q>[public]::a2
00025) + 1:1 coerce <q>[public]::Function
00026) + 1:1 setlocal_3
 
/* qqq(); */
00027) + 0:1 getlocal_1
00028) + 1:1 getglobalscope
00029) + 2:1 call 0 params
00030) + 1:1 pop
 
/* www(); */
00031) + 0:1 getlocal_2
00032) + 1:1 getglobalscope
00033) + 2:1 call 0 params
00034) + 1:1 pop
 
/*qwe();*/
00035) + 0:1 getlocal_3
00036) + 1:1 getglobalscope
00037) + 2:1 call 0 params
00038) + 1:1 pop
 
/* qqq.call(test2); */
00039) + 0:1 getlocal_1 // сложили в стек qqq
00040) + 1:1 getlocal_0 // сложили в стек себя
00041) + 2:1 getproperty <q>[private]NULL::test2 // поискали в себе test2, соответственно на макушке стека теперь не указатель на нас а указатель на test2
00042) + 2:1 callpropvoid <q>[namespace]http://adobe.com/AS3/2006/builtin::call, 1 params // вызвали call, он как и constructSuper ест на один параметр больше чем указанное количество параметров, т.е. он захавает test2 и qqq что лежали на верхушке стека.
 
/* qqq.apply(test2); */
00043) + 0:1 getlocal_1 // тут всё абсолютно аналогично, дублировать не стал.
00044) + 1:1 getlocal_0
00045) + 2:1 getproperty <q>[private]NULL::test2
00046) + 2:1 callpropvoid <q>[namespace]http://adobe.com/AS3/2006/builtin::apply, 1 params
Собственно ничего неожиданного на уровне abc байткода, обычным образом засавали функцию и потом обычным образом вызвали. call и apply получили правильные параметры. Почему такие результаты трейса в упор не могу понять.


Последний раз редактировалось iNils; 29.11.2010 в 18:49.
Старый 29.11.2010, 19:03
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 2  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
Цитата:
то получаем два разных экземпляра функций которые обрабатывают разный объект(test1 и test2 соответственно).
Нет, вы получаете ссылки именно на две функции. Уже без привязки к объектам к которым они изначально относились. Функция это тоже объект.
В данном случае this будет ссылаться на класс в котором будут вызваны эти функции.

Добавлено через 10 минут
Хотя возможно я перепутал с Java. Сейчас проверю.

Старый 29.11.2010, 19:14
Aquahawk вне форума Посмотреть профиль Отправить личное сообщение для Aquahawk Посетить домашнюю страницу Aquahawk Найти все сообщения от Aquahawk
  № 3  
Ответить с цитированием
Aquahawk
 
Аватар для Aquahawk

Регистрация: Nov 2010
Адрес: Москва
Сообщений: 915
Записей в блоге: 4
Отправить сообщение для Aquahawk с помощью ICQ Отправить сообщение для Aquahawk с помощью Skype™
Я об этом и говорю что функций получается две, вызывать их можно отдельно, но вот объект от которого их оторвали они помнят, это показывают результаты трейса. Вопрос в том как это работает и как этим управлять. Знать надо досконально т.к. мне нужно это написать в байткоде, без компилятора.

Старый 29.11.2010, 19:20
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 4  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
Разница все таки есть.
Цитата:
Методы класса немного отличаются от объектов Function. В отличие от обычного объекта функции метод тесно связан со связанным объектом класса. Поэтому метод или свойство имеют определение, используемое всеми экземплярами одного и того же класса. Из экземпляра можно извлечь методы, обрабатываемые как «связанные» методы (сохраняющие ссылку на исходный экземпляр). В рамках связанного метода ключевое слово this указывает на исходный объект, реализовавший этот метод. В случае функции this указывает на связанный объект на момент вызова функции.
Добавлено через 3 минуты
Если хотите создать именно функцию, то это делается несколько иначе:
Код AS3:
var foo:Function = function():String { return "i just function" }


Последний раз редактировалось alatar; 29.11.2010 в 19:47.
Старый 29.11.2010, 19:29
Aquahawk вне форума Посмотреть профиль Отправить личное сообщение для Aquahawk Посетить домашнюю страницу Aquahawk Найти все сообщения от Aquahawk
  № 5  
Ответить с цитированием
Aquahawk
 
Аватар для Aquahawk

Регистрация: Nov 2010
Адрес: Москва
Сообщений: 915
Записей в блоге: 4
Отправить сообщение для Aquahawk с помощью ICQ Отправить сообщение для Aquahawk с помощью Skype™
Слепой, только что читал но не увидел. Ладно, пусть официально указано что метод хранит указатель на свой объект, на то и похоже. Но мы же сохраняем в переменную типа Function и в abc коде происходит приведение типа: coerce <q>[public]::Function. И почему не работает call() и apply() тоже в упор не понятно.

Старый 29.11.2010, 19:35
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 6  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
Цитата:
Но мы же сохраняем в переменную типа Function
При чем здесь тип? Если попробуете поставить другой, получите ошибку. Методы имеют тип Function.
Цитата:
И почему не работает call() и apply() тоже в упор не понятно.
Они работают. Причем так, как написано в хелпе.

Старый 29.11.2010, 19:38
Aquahawk вне форума Посмотреть профиль Отправить личное сообщение для Aquahawk Посетить домашнюю страницу Aquahawk Найти все сообщения от Aquahawk
  № 7  
Ответить с цитированием
Aquahawk
 
Аватар для Aquahawk

Регистрация: Nov 2010
Адрес: Москва
Сообщений: 915
Записей в блоге: 4
Отправить сообщение для Aquahawk с помощью ICQ Отправить сообщение для Aquahawk с помощью Skype™
qqq.call(test2); игнорирует указанный test2 и инкрементирует a содержащуюся в test1, хотя написано что он проигнорирует свой this и заменит его на пришедший в качестве параметра.

Старый 29.11.2010, 19:41
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 8  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
Где это написано? Написано как раз противоположное.
Создайте именно функцию (не метод) и все встанет на свои места.

Добавлено через 1 минуту
Цитата:
В рамках связанного метода ключевое слово this указывает на исходный объект, реализовавший этот метод.
Это ваш случай.
Цитата:
В случае функции this указывает на связанный объект на момент вызова функции.
А это относится к функциям, а не к методам.

Старый 29.11.2010, 19:53
Aquahawk вне форума Посмотреть профиль Отправить личное сообщение для Aquahawk Посетить домашнюю страницу Aquahawk Найти все сообщения от Aquahawk
  № 9  
Ответить с цитированием
Aquahawk
 
Аватар для Aquahawk

Регистрация: Nov 2010
Адрес: Москва
Сообщений: 915
Записей в блоге: 4
Отправить сообщение для Aquahawk с помощью ICQ Отправить сообщение для Aquahawk с помощью Skype™
Цитата:
В некоторых ситуациях может потребоваться, чтобы thisObject указывал на другой объект (например, если функцию необходимо вызвать как метод объекта, но на самом деле она не сохраняется как метод этого объекта):
myObject.myMethod.call(myOtherObject, 1, 2, 3);
Собственно такого поведения и жду.

Старый 29.11.2010, 19:58
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 10  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
В данном примере myMethod это свойство (типа Function) класса, к которому относится экземпляр myObject, которое содержит анонимную функцию.

Создать новую тему Ответ Часовой пояс GMT +4, время: 02:53.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 02:53.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.