Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Общие вопросы о Flash (не затрагивающие ActionScript) (http://www.flasher.ru/forum/forumdisplay.php?f=60)
-   -   Полезность класса Delegate (http://www.flasher.ru/forum/showthread.php?t=87208)

wvxvw 31.10.2006 18:53

Полезность класса Delegate
 
Вот недавно столкнулся с такой штукой... Знакомый попросил помочь разобраться с кодом. Описывать что там и как не буду, главное, там была загвоздка с использованием Delegate. Я как-то давно почитав описание этого класса, возможно, особо не вникая, решил, что это вобщем-то бесполезная штука. Т.как на сколько я понял - нужен он для того, чтобы переопределить this для вызываемой функции. Но если строить функции так, что они нигде не обращаются к this, а все объекты с которыми они работают передаются им в параметрах, то нет никакой необходимости в использовании Delegate...

Собственно, вопрос-просьба, если кому не лень... Объясните, мб, я не правильно понял назначение класса. Ну или по крайней мере приведите пример, где использование этого класса предпочтительно\необходимо. Потому что как ни крути, у меня получается просто, как минимум несколько "лишних" строчек кода, если я пытаюсь сделать что-то с использованием Delegate.

miramax 31.10.2006 19:37

Я тоже не юзаю Delegate.
Но умные люди твердят, что это нужно для простоты понимая иерархии классов, для логического разделения методов между классами.

etc 31.10.2006 20:05

Delegate используется в силу того, что многие объекты во Flash 8 (и ниже) не являются вещателями, т.е. невозможно подписаться на события объекта.
Есть некий класс, который занимается обработкой данных, полученных из XML. Обработка — задача именно этого класса, а не объекта XML (как раз то, о чём пишет miramax). Поэтому, т.к. подписаться на onLoad нельзя, используется перенаправление вызова данного метода в метод нашего класса, т.е. как бы подписка на события.

У меня есть класс AbstractXML, который является вещателем, вот как он выглядит:
Код:

import mx.events.EventDispatcher;
/**
 * @author Denis Kolyako
 */
class ru.etcs.data.AbstractXML extends XML {
       
        private var __xml_url:String;
       
        public var event:String = 'onXMLLoad';
        public var errorEvent:String = 'onXMLLoadError';
        public var idMap:Object;

        private var dispatchEvent:Function;
        public var addEventListener:Function;
        public var removeEventListener:Function;
                       
        public function AbstractXML(xml_url:String) {
                super("");
                this.ignoreWhite = true;
                EventDispatcher.initialize(this);
                this.__xml_url = xml_url;
                this.load(this.__xml_url);
        }
               
        private function onLoad(ok:Boolean):Void {
                if (!ok || !this.loaded || this.status || this.getBytesTotal()<30) {
                        trace('XML loaded: '+this.loaded+', valid: '+this.status);
                        this.dispatchEvent({type:this.errorEvent});
                        return;
                }       
                this.prepareData();
                this.dispatchEvent({type:this.event});
        }
       
        private function prepareData():Void {
                // For override       
        }

}

И у меня нет необходимости перенаправлять вызовы, я просто подписываюсь на события (имена которых, для удобства, можно изменить).

wvxvw 31.10.2006 22:07

2 __etc:
Я уже видел этот код в другом топе... там же я написал, каким образом решил бы проблему отслеживания загрузки ХМЛя, если бы я использовал кастомный класс, подкласс ХМЛя. Мой код вышел короче + не нужно было импортировать классы по умолчанию не включающиеся при публикации...
Т.е. вопрос, по крайней мере для меня, по прежнему открыт. Не вижу в таком решении ни упрощения ни оптимизации. На лицо факт - конечная флешка в результате использования такого подхода просто немного вырастет в размерах (скорость работы думаю не изменится, с чего бы).

etc 01.11.2006 01:06

А я вижу в таком решение упрощение и оптимизацию:
а) Я не создаю лишних ссылок и переменных
б) Область видимости в классе остаётся всегда одной и той же
в) Каждый класс занимается тем, чем ему положено и ничем иным

Дело не в сокращении кода, а в исключении досадных ошибок. Я никогда не повторю оператор function внутри метода, потому что из-за этого могут возникнуть проблемы, вроде пропадания внешней переменной, не говоря уже о том, что будешь сбит другой областью видимости внутри функции.

В AS3 тебе нужно будет подписывать на события, мой AbstractXML близок по духу к AS3 и у меня врядли возникнут сложности в работе с AS3.

Впрочем, если вам удобно писать так, как вы пишите — пожалуйста. Это не более, чем просто рекомендации. Я не скажу, что прям уж так знаю все принципы ООП, но главный из них — минимальную связь между классами стараюсь соблюдать.

wvxvw 01.11.2006 05:36

В таком случае (чтобы не допустить ошибку) я лучше комент напишу... Затраты по времени ровно точно такие же, но на конечный результат не повлияет. Ну и меня нисколько не смущает то, что один и тот же класс будет и загружать и разбирать ХМЛ, как правило именно это и нужно, а не 2 класса, один для загрузки, второй для разборки. Более того, мне скорее даже нравится то, что не нужно плодить лишние сущности в виде многочисленных классов, в которых, на мой взгляд, как раз таки легче запутаться.
Кроме того, я бы не назвал ссылку\переменную лишней если она упрощает доступ к нужному свойству. В конце концов чем отличается переменная\ссылка в классе от практически такой же ссылки на листенер? Смысл-то самой операции нисколечки не меняется, просто в случае с Delegate нужно написать на пару строчек больше...

Т.е. если я правильно понял, практической пользы в Delegate все таки нет? Исключительно "организационный момент"? Т.е. даже теоретически не может существовать случая когда бы его использование привело к лучшему результату (меньший объем кода \ большая производительность)?
ЗЫ. Можно спать спокойно? =)

etc 01.11.2006 07:02

Похоже, мне вас переубедить вообще не удастся.

Ссылка, которая определяется вне функции может вообще не существовать внутри того же onLoad! Это лишняя ссылка. Дело не в упрощении, а в возможной потери контроля над ситуацией.

Если делать более менее правильно (слабые связи) — нужно делать класс, расширяющий XML и являющийся вещателем (в AS3 это так и есть). Далее, если всё же использование такого класса неприемлимо — Delegate, в этом случае потери логики и сваливания чужих функций в другой класс не происходит. А если писать так, как вы предлагаете:
Код:

var classInstance:AnyClass = this;
this.anyXML.onLoad = function(success:Boolean):Void {
    this.xmlDecl = ''; // Ага, а куда ссылается this? FDT даст по рукам сразу же
    classInstance.onXMLLoad();
};

То это мало того, что ухудшает читабельность и разбор кода, но ещё может привести к ошибкам, к той же потери этой самой ссылки classInstance. Если же добавлять ссылку к самому XML (this.anyXML.classInstance = this), то у него вообще-то нет никакой такой ссылки. Более того, если у вас больше, чем один XML, но действия выполняемые после загрузки одинаковы, то две-три или десяток таких конструкций точно будет сложно разобрать.
Я уже не говорю про какие-нибудь кнопки, которым нужно прописать обработчики onRelease, onPress…

В общем, если не хотите использовать Delegate — не используйте, я же не заставляю :D
А я же не буду создавать себе дополнительных сложностей в виде создания каких-то ссылок, непоняток с областью видимости и вообще, заниматься описанием методов одного класса в описании другого (когда этот метод по факту должен быть описан в данном классе, а не в каком-нибудь XML) — у меня других забот хватает.

К тому же, бывают ситуации, где Delegate просто необходим (случай с XML — тривиальный, найду посложнее — покажу) и он является отличным инструментом. В AS3 он не нужен, все объекты (кроме некоторых, разумеется) являются наследниками EventDispatcher и можно просто подписаться на события.

Если вам понадобиться переписать проект на AS3, то вам придёться переписывать весь код (даже хотя бы просто потому что он неприемлим в AS3, это в AS1 сплошь и везде так писали). В случае с Delegate — заменить одну строку. В случае уже использования класса-надстройки — или удалить класс и поменять везде на XML или же, если в этом классе есть доп. методы, убрать инициализацию диспетчером и объявление его методов. Всё, никаких проблем нет.

Впрочем, не хотите — не пишите. Если для вас пользы нет, значит нет.

wvxvw 01.11.2006 16:44

2 __etc:
И все-таки вы меня не поняли... Я не противник и не сторонник использования этого класса. Я просто не понимаю зачем он нужен. Пример в посте №7 ничего не объясняет... или я не понял, что он должен был бы объяснять... Я же не сравниваю неработающий код с работающим. Я сравниваю результат двух работающих кодов. Т.е. если я увижу, что Delegate в каком-то конкретном случае или сокращает время написания кода, или уменьшает итоговый вес файла, или увеличивает быстродействие - я с радостью буду его там использовать. Просто пока что я не видел случая когда бы с прагматических позиций использование Delegate было оправдано. Буду очень признателен, если вы покажете какой-нибудь пример, где именно с этих позиций использование Delegate дает плюсы.

MyXus 01.11.2006 16:50

Не читал, много букв.
Карочи, delegate правильно выставляет область видимости функции. Это ничем не лучше работает, просто корректнее.


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

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