Comments 42
Кстати, в this функции onGetResult будет уже не экземпляр Example, а просто global.Не совсем :) там будет не global, а некая обертка объектов текущего *.as файла (именно файла, а не пакета, и не global), она находится чуть ниже в scope-очереди, однако позволяет достучаться вплоть до global.
+1
Да, повидимому так и есть. Я имел ввиду, что будет контекст не текущего родителя (класса, функции), а что-то более глобальное =)
0
Стоит отметить, что с усложненеим кода в onGetResult, значительно усложнится и поиск багов.
И надо иметь хорошие знания и опыт в цепочке видимости (scope-chain) и постоянно понимать что onGetResult — это вовсе не метод а функциональная кложура (не знаю как перевести closure, но слово «кожура» — кстати, подходит :)
В командной разработке, думаю, лучше не прибегать к таким методам, ато у новичков от постоянных багов сорвет башню.
И надо иметь хорошие знания и опыт в цепочке видимости (scope-chain) и постоянно понимать что onGetResult — это вовсе не метод а функциональная кложура (не знаю как перевести closure, но слово «кожура» — кстати, подходит :)
В командной разработке, думаю, лучше не прибегать к таким методам, ато у новичков от постоянных багов сорвет башню.
0
Ну, в общем-то, не обязательно помещать много кода в onGetResult, думаю правильным решением будет делегирование обработки вспомогательному классу или просто продиспатить ивент.
На практике, даже в очень больших и запутанных бизнес-логикой проектах, подобные решения как раз таки упрощали код и его понимание. Как минимум на предмет отстутствия бесконечных временных приватных переменных классов для сохранения обрабатываемых объектов.
На практике, даже в очень больших и запутанных бизнес-логикой проектах, подобные решения как раз таки упрощали код и его понимание. Как минимум на предмет отстутствия бесконечных временных приватных переменных классов для сохранения обрабатываемых объектов.
0
Руки бы отрывал за вложенные функции.
0
А вы на них смотрите как на именованные замыкания — и полезно, и руки отрывать не надо :))
+2
Объясните мне, почему?
0
Да потомучто нереально их дебажить это раз, и предсказать их поведение — тоже
-1
Ну, может быть ваша ІDE сталкивается с проблемами при отладке, в Flex Builder всё великолепно. А вот для того, чтобы поведение предсказывалось, я и написал данную статью. Надеюсь, хоть чем-то она кому-то поможет.
-1
как ни странно работаю во Flex IDE
Такой не скромный вопрос, вы когда-нибудь работали в команде хотя бы 5+ человек?
Такой не скромный вопрос, вы когда-нибудь работали в команде хотя бы 5+ человек?
0
Я тим-лид команды флексеров (4 человека) =)
Ранее всегда работал в командах от 3-4 человек. Я понимаю, что вы стандартно клоните, к тому, что такой код тяжело сопровождать новичкам на проектах — это абсурд. В вышеприведённом коде нет особо секретных костылей или дёрти-хаков, он прост как визуально так и семантически.
Ранее всегда работал в командах от 3-4 человек. Я понимаю, что вы стандартно клоните, к тому, что такой код тяжело сопровождать новичкам на проектах — это абсурд. В вышеприведённом коде нет особо секретных костылей или дёрти-хаков, он прост как визуально так и семантически.
-1
эхххх флексеры… не буду ничего говорить. вы бы еще хендлеры запихивали как вложенные функции и тогда бы проекты бы после открытия сжирали по 300 метров… все молчу.
+1
Кстати, да, засовываем довольно успешно. Пользуемся слабыми ссылками при добавлении подобных хендлеров, в результате сборщик мусора отлично их подчищает.
-2
Мое ИМХО — Слабые ссылки зло, сборщик мусора нам не подконтролен, если подписался сам же и отпишись. Я так делаю и никому этот путь не навязываю. Спор беспочвенен.
+2
Слабые ссылки при добавлении ивент хендлеров это дополнительный инструмент, который предоставила Адобе. Правильно пользуясь ими, можно сэкономить в коде и не добавлять в стройную архитектуру проекта вынужденое «уничтожение» для некоторых объектов.
Да и ещё раз да, листенеры нужно удалять вручную, причём, желательно, в тех же местах где они были добавлены. Но, бывают ситуации, когда достаточно расчитывать на слабые ссылки. Если желаете могу приподнести простой пример.
Да и ещё раз да, листенеры нужно удалять вручную, причём, желательно, в тех же местах где они были добавлены. Но, бывают ситуации, когда достаточно расчитывать на слабые ссылки. Если желаете могу приподнести простой пример.
0
Ваш код заставляет мои глаза кровоточить. Если уж перешли на AS3, то тогда забудьте про AS2 и включите strict mode раз и навсегда.
+1
Не очевидно, почему нужно забыть AS2, только потому, что версия 3 счастливое число?
Режим strict mode включён всегда, надеюсь у вас тоже.
Режим strict mode включён всегда, надеюсь у вас тоже.
-1
Прошу прощения что так сразу накинулся, попробую объяснить.
Возьму пример из начала текста.
Функцию-то описать можно, но этот код не скомпилируется в том виде, в каком вы его привели, т.к. отсутствует конструктор, принимающий параметр. Будет сгенерирован по дефолту пустой конструктор, который не принимает аргументов, и при попытке туда что-то передать вылезет ошибка.
Я допускаю, что наличие правильного конструктора подразумевается, но это не для всех очевидно, некоторых читателей вы вводите в заблуждение.
Кстати вообще для создания таких функций я бы лучше воспользовался статическим методом класса, вместо того, чтобы для каждой новой функции плодить объекты, которые будут висеть в памяти до великого пришествия GC.
Ещё пример:
Далеко не сразу я нашёл объявление _tempObject. Когда я в первый раз читал статью, я решил что оно вообще пропущено, и думаю, не я один. Учитывая тему, к которой относится пример, сразу становится неочевидно, к какой области видимости относится данная переменная, что вносит большую путаницу. Просто потому что переменные и константы всегда определяются до описания методов. Хотя тут я скорее всего придираюсь к мелочам.
Надеюсь, вы воспримете это как конструктивную критику, или даже убедите меня в моей неправоте. Ибо споры между уважающими друг друга оппонентами — процесс довольно приятный и познавательный :)
Возьму пример из начала текста.
Например, теперь можно описать такую функцию:
public class TestClass { var property : Number; function updateValue(value : Number) : void { TestClass(this).property = value; } }
Функцию-то описать можно, но этот код не скомпилируется в том виде, в каком вы его привели, т.к. отсутствует конструктор, принимающий параметр. Будет сгенерирован по дефолту пустой конструктор, который не принимает аргументов, и при попытке туда что-то передать вылезет ошибка.
Я допускаю, что наличие правильного конструктора подразумевается, но это не для всех очевидно, некоторых читателей вы вводите в заблуждение.
Кстати вообще для создания таких функций я бы лучше воспользовался статическим методом класса, вместо того, чтобы для каждой новой функции плодить объекты, которые будут висеть в памяти до великого пришествия GC.
Ещё пример:
class Example { function updateItem(item : SomeObject) : void { _tempObject = item; new ServerService(onGetResult).getResult(item.startValue); } function onGetResult(result : Object) : void { _tempObject.endValue = result; } private var _tempObject : SomeObject; }
Далеко не сразу я нашёл объявление _tempObject. Когда я в первый раз читал статью, я решил что оно вообще пропущено, и думаю, не я один. Учитывая тему, к которой относится пример, сразу становится неочевидно, к какой области видимости относится данная переменная, что вносит большую путаницу. Просто потому что переменные и константы всегда определяются до описания методов. Хотя тут я скорее всего придираюсь к мелочам.
Надеюсь, вы воспримете это как конструктивную критику, или даже убедите меня в моей неправоте. Ибо споры между уважающими друг друга оппонентами — процесс довольно приятный и познавательный :)
0
По-поводу TestClass, зачем так конструктор? Он не нужен, в примере использования ничего в класс не передаётся:
Да, в первом примере можно использовать статический метод, а можно вообще ничего не использовать — пример фиктивен. Это просто предисловие к основной теме про контексты, не стоит его воспринимать буквально.
По-поводу _tempObject, даже не знаю как прокоментировать, это не то что-бы придирание к мелочам, это какое-то тонкое издевательство, надеюсь вы шутили =).
var func: Function = new TestClass().updateValue;
Да, в первом примере можно использовать статический метод, а можно вообще ничего не использовать — пример фиктивен. Это просто предисловие к основной теме про контексты, не стоит его воспринимать буквально.
По-поводу _tempObject, даже не знаю как прокоментировать, это не то что-бы придирание к мелочам, это какое-то тонкое издевательство, надеюсь вы шутили =).
0
По поводу _tempObject я пожалуй погорячился, будем считать что я шутил :)
Про конструктор я говорил относительно этой строчки:
TestClass(this).property = value;
Про конструктор я говорил относительно этой строчки:
TestClass(this).property = value;
0
Это:
операция приведения типов, сдесь она не обязательна, я написал для наглядности.
Не следует путать запись выше с:
TestClass(this)
операция приведения типов, сдесь она не обязательна, я написал для наглядности.
Не следует путать запись выше с:
new TestClass(this)
0
Публично признаю себя слепым идиотом, не сумевшим отличить кастинг от создания экземпляра. Хотя осознание того, что это кастинг, делает эту строчку ещё более загадочной =)
Какую логику вы в неё закладываете?
Какую логику вы в неё закладываете?
0
Что-бы подчеркнуть, что this это екземпляр класса TestClass, а не что-либо другое. В противном случае будет ошибка времени исполнения.
0
Тогда мне кажется лучше использовать this as TestClass, т.к. эти касты вроде отличаются. Пойду погуглю.
0
Не лучше, оператор as — это так же оператор приведения типа, но тихий. Если приводимый объект, будет другого типа, то оператор вернёт null и эксепшена не будет. В этом основная разница.
0
Имхо кастинг в данном случае — это уже паранойя, классы должны быть чёрными ящиками, но сами себе-то они могут доверять! В конце концов это вы создаёте код, и совершенно сознательно пишете данный метод в этом классе. Надо больше в себя верить! :)
0
Несомненно! Но, так как речь идёт о сохраняемом контексте функций, то данная запись подчёркивает что this(контекст) будет именно таким как и ожидается. В AS2 например, этот же код выполнился бы с эксепшеном, так как this не был бы экземпляром класса TestClass, но того класса, в котором функция бы вызывалась.
Это и есть суть примера, который не стоит принимать как пример для написания кода, только для понимания.
Это и есть суть примера, который не стоит принимать как пример для написания кода, только для понимания.
0
/*
В as2 эта строчка бы выкинула эксепшен, так как метод исполнился бы не в контексте нашего класса, а в том контексте, откуда он был вызван.
*/
Один коммент мог заменить всю нашу беседу :)
В as2 эта строчка бы выкинула эксепшен, так как метод исполнился бы не в контексте нашего класса, а в том контексте, откуда он был вызван.
*/
Один коммент мог заменить всю нашу беседу :)
0
Надеюсь, беседа будем полезна как вам, так и тем, кто возможно её прочитает.
0
Несомненно, уже нашлись заинтересованные:
flasher.ru/forum/showthread.php?t=122122
flasher.ru/forum/showthread.php?t=122122
0
ого, в AS2 есть exception-ы на null object reference-ы:) почему все остальные флешеры этого не знали?:)
0
Каково еще применение вложенных функций кроме описанного?
Про хендлеры было упоминание выше, я согласен, что полагаться на сборщик не стоит, да и дебажить такие конструкции не слишком удобно.
Кроме того, лично для меня польза того, что обработчик находится в вызывающим асинхронный запрос методе (а по сути в одной области видимости) не совсем очевида. Буду рад если объясните.
Про хендлеры было упоминание выше, я согласен, что полагаться на сборщик не стоит, да и дебажить такие конструкции не слишком удобно.
Кроме того, лично для меня польза того, что обработчик находится в вызывающим асинхронный запрос методе (а по сути в одной области видимости) не совсем очевида. Буду рад если объясните.
0
Предпочитаю не полагаться на сборщик, а контролировать его посекундно. Для этого мы имеем неплохой инструмент от Адоби, называется Flex Builder Profiler. В нём можно видеть, сколько объектов или функций не уничтожилось, сколько памяти израсходовано. Зачем гадать? Можно же проверить! =)
В чём неудобство отладки таких конструкций? Брейкпоинты в них обрабатываются Flex Builder-ом, стек трейс и состояние памяти показается. Где неудобства?
Да, основная суть предложеных подходов — сокращение объёма кода и улучшение семантики асинхронного кода (не разрывая её приватными переменными для временного хранения обрабатываемых объектов). Если вам это не нужно — не используйте.
Есть ещё несколько вариантов использования вложеных функций, например передавая их в методы массивов forEach(), filter() — им будут доступны все переменные родительской функции и это можно использовать для поэлементной обработки.
В чём неудобство отладки таких конструкций? Брейкпоинты в них обрабатываются Flex Builder-ом, стек трейс и состояние памяти показается. Где неудобства?
Да, основная суть предложеных подходов — сокращение объёма кода и улучшение семантики асинхронного кода (не разрывая её приватными переменными для временного хранения обрабатываемых объектов). Если вам это не нужно — не используйте.
Есть ещё несколько вариантов использования вложеных функций, например передавая их в методы массивов forEach(), filter() — им будут доступны все переменные родительской функции и это можно использовать для поэлементной обработки.
0
Судя по опыту, в отношении GC — не следует так сильно полагаться. Так в профайлере (debug-версия плеера) и продакшн-версии (обычный плеер) — могут быть совершенно различные картины.
0
Sign up to leave a comment.
Контексты функций в Action script