Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Экземпляр какого класса придет в листенер. Часть 2 (http://www.flasher.ru/forum/showthread.php?t=210420)

callme 11.03.2015 18:36

Экземпляр какого класса придет в листенер. Часть 2
 
На самом деле это продолжение старого топика. Но старый топик стал таким запутанным, что я решил подвести итог и начать новый топик.

Итог:

Пример: Человек может купить собаку. При этом он посылает кастомное событие, в котором лежит собака.


Код AS3:

package
{
    [Event(name = "iBoughtDog", type = "ManEvents")]
 
    public class Main
    {
        public function Main()
        {
            var man:Man = new Man();
            man.addEventListener(ManEvent.I_BOUGHT_DOG, listener);
        }
 
        private function listener( сноска* ):void
        {
 
        }
    }
}
 
package
{
    [Event(name = "iBoughtDog", type = "ManEvent")]
 
    public class Man
    {
        public function Man()
        {
 
        }
 
        private function someFunction():void
        {
            dispatchEvent( new TransportEvent(dog, ManEvent.I_BOUGHT_DOG) );
        }
    }
}
 
package
{
    public class ManEvent
    {
        static public const I_BOUGHT_DOG:String = "iBoughtDog";
    }
}
 
package
{
    import flash.events.Event;
 
    public class TransportEvent extends Event
    {
        public function TransportEvent(cargo:Object, type:String, bubbles:Boolean=false, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
            _cargo = cargo;
        }
 
        public function get cargo():Object { return _cargo; }
 
        private var _cargo:Object;
    }
}

Проблема в том, что мы ожидаем, что в слушатель события придет экземпляр класса ManEvent, а придет туда TransportEvent.

Для решения проблемы можно отнаследовать ManEvent от TransportEvent и посылать в слушатель именно ManEvent.

Код AS3:

package
{
    public class ManEvent extends TransportEvent
    {
        static public const I_BOUGHT_DOG:String = "iBoughtDog";
 
        public function ManEvent(cargo:Object, type:String, bubbles:Boolean=false, cancelable:Boolean=false)
        {
            super(cargo, type, bubbles, cancelable);
        }
    }
}

Но наследование выглядит глупо - ведь мы никак не расширили базовый класс.

caseyryan 11.03.2015 18:49

Зачем вообще наследовать события? Вполне достаточно унаследовать свой класс от базового класса Event и не городить никаких длинных цепочек.
И зачем передавать эту собаку в конструкторе? Можно сделать у события публичное свойство dog и передавать его туда.

п.с. не стоило создавать новую тему

callme 11.03.2015 19:10

По всему проекту разбросаны кучи однотипных классов.

Код AS3:

package 
{
    import flash.events.Event;
 
    public class SomeEvent extends Event
    {
        public function SomeEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
        }
 
        public var something:Something;
    }
}

Все эти классы выполняют одну и ту же роль. Нести какой-то объект.

Я решил удалить все эти классы, и создал TransportEvent, который несет нетипизированный объект.

GBee 11.03.2015 19:24

Цитата:

Проблема в том, что мы ожидаем, что в слушатель события придет экземпляр класса ManEvent, а придет туда TransportEvent.
Цитата:

Код AS3:

dispatchEvent( new TransportEvent(dog, ManEvent.I_BOUGHT_DOG) );


Непонятно, чего вы ожидаете, но получаете то, что отсылаете.

Добавлено через 7 минут
у пришедшего события (TransportEvent) будет type == ManEvent.I_BOUGHT_DOG

callme 11.03.2015 19:36

С помощью метатегов event мы можем указать редактору кода, какие события может отправлять Man.

А как узнать какой объект придет в слушатель, не залезая в Man?

caseyryan 11.03.2015 19:41

Цитата:

А как узнать какой объект придет в слушатель, не залезая в Man?
Никак. Нужно писать код правильно. И не будет возникать таких нелепых задач.
Если есть Man и ManEvent, то не должен Man отправлять никаких TransportEvent. Он должен слать ManEvent, чтобы все было интуитивно понятно.

GBee 11.03.2015 19:50

Цитата:

А как узнать какой объект придет в слушатель, не залезая в Man?
По типу события, я же вам спецом дополнил.

callme 11.03.2015 20:02

Цитата:

Сообщение от GBee (Сообщение 1179913)
По типу события, я же вам спецом дополнил.

Я хочу узнать тип параметра функции listener.

Код AS3:

function listener(*что сюда прийти должно*):void
{
 
}

Добавлено через 4 минуты
caseyryan, я описал тут почему я хочу попробовать новый подход.

caseyryan 11.03.2015 20:27

Цитата:

caseyryan, я описал тут почему я хочу попробовать новый подход.
Мы говорим о разных вещах. Похоже у вас не четкое представление о наследовании в ООП
Зачем нужно посылать TransportEvent, пытаясь его выдать за ManEvent, когда можно просто сделать свойство в TransportEvent публичным, и оно будет доступно как в ManEvent, так и в TransportEvent и в других местах, где есть доступ к объекту ManEvent или TransportEvent.
Что мешает сделать так?
Код AS3:

package  {
        import flash.events.Event;
 
        /**
        * ...
        * @author Konstantin
        */

        public class TransportEvent extends Event {
 
 
 
                public var dog:Object = null;
 
                public function TransportEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
                        super(type, bubbles, cancelable);
 
                }
 
                public override function clone():Event {
                        var event:TransportEvent = new TransportEvent(type, bubbles, cancelable);
                        event.dog = this.dog;
                        return event;
                }
 
                public override function toString():String {
                        return formatToString("TransportEvent", "type", "bubbles", "cancelable", "eventPhase");
                }
 
        }
 
}
package  {
        import flash.events.Event;
 
        /**
        * ...
        * @author Konstantin
        */

        public class ManEvent extends TransportEvent {
                public static const DOG_BUY:String = "dogBuy";
 
                public function ManEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
                        super(type, bubbles, cancelable);
 
                }
 
                public override function clone():Event {
                        var event:ManEvent = new ManEvent(type, bubbles, cancelable);
                        event.dog = this.dog;
                        return event;
                }
 
                public override function toString():String {
                        return formatToString("ManEvent", "type", "bubbles", "cancelable", "eventPhase");
                }
 
        }
 
}
 
// а где-то в классе Man
var event:ManEvent = new ManEvent(ManEvent.DOG_BUY);
event.dog = какаяТоСобака;
dispatchEvent(event);
 
// и, соответственно, слушать надо будет ManEvent.DOG_BUY


callme 11.03.2015 20:37

Пусть будет публичное. Это никак не влияет на суть вопроса.

Зачем у вас класс ManEvent расширяет TransportEvent? Что он умеет нового по сравнению с TransportEvent?

caseyryan 11.03.2015 20:41

Цитата:

Что он умеет нового по сравнению с TransportEvent?
Он содержит собственные константы, которые присущи только человеку. Вот что нового.
А расширяет TransportEvent для того, чтобы унаследовать от него свойство dog
Даже если бы он вообще ничего не умел нового и констант не содержал, он все равно должен был бы быть, потому что Man должен посылать ManEvent, а не какой-то там TransportEvent.

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

callme 11.03.2015 20:58

Цитата:

Цитата:

Что он умеет нового по сравнению с TransportEvent?
Он содержит собственные константы, которые присущи только человеку. Вот что нового.
Это к наследованию не имеет отношения.

Цитата:

Вообще, исходя из вашей логики, не надо создавать вообще никаких лишних классов. Можно весь код писать в одном полотенце Main и не париться, аккуратно раскладывая все по полочкам.
А по вашей логике давайте будем интерфейсы плодить по каждому поводу для читабельности, пусть вместо DisplayObject в функцию приходит например IHaveXY.

caseyryan 11.03.2015 21:15

Что ж, удачи тогда с изобретением новых концепций)

GBee 11.03.2015 21:32

Цитата:

Сообщение от callme (Сообщение 1179914)
Я хочу узнать тип параметра функции listener.

Код AS3:

function listener(*что сюда прийти должно*):void
{
 
}


TransportEvent приходит и смотрите его type в зависимости от типа можно понять что вы запихнули в cargo

Код AS3:

dispatchEvent( new TransportEvent(dog, ManEvent.I_BOUGHT_DOG) );
dispatchEvent( new TransportEvent(cat, ManEvent.I_FOUND_CAT) );
dispatchEvent( new TransportEvent(iam, ManEvent.I_DONT_KNOW_EVENT_S_LOGIC) );
 
function listener(event:TransportEvent):void
{
    switch(event.type)
    {
        case ManEvent.I_BOUGHT_DOG:
            event.cargo.createNoise();
        break;
        case ManEvent.I_FOUND_CAT:
            event.cargo.makeMyauMyau();
        break;
        case ManEvent.I_DONT_KNOW_EVENT_S_LOGIC:
            event.cargo.openAdobeHelp();
        break;
    }
 
}

Добавлено через 1 минуту
Ну или разные слушатели для разных типов событий.

Wolsh 11.03.2015 21:41

Цитата:

он все равно должен был бы быть, потому что Man должен посылать ManEvent, а не какой-то там TransportEvent.
Не вижу ничего зазорного в том, что люди отправляют грузовики.
Цитата:

пусть вместо DisplayObject в функцию приходит например IHaveXY
Вот тут Вы вообще не туда наступили. Не приписывайте Кейси глупости, основанные на неведении. Это не его мысль, а Ваша.
Проблема вобщем в том, что addEventListener принимает подозрительную строку а не тип События. И этого нам не исправить, увы (иногда не увы а ура, но здесь кажется увы).
Вцелом я вообще не вижу никакой проблемы, кроме "мы ожидаем", потому что "мы" же и использовали константу из другого класса. Ну так не ожидайте. Во всех случаях, когда мы используем обычный Event со своим строковым типом, мы имеем ровно эту проблему — подписываемся на какую-то левую строку, а получаем в хэндлер стандартный Event. И все довольны.
Либо напишите пресловутый ManEvent extends TransportEvent, как советует Кейси. Только наверное нет смысла добавлять к "грузу" еще и "собаку")))))

callme 11.03.2015 22:14

Цитата:

Не приписывайте Кейси глупости, основанные на неведении. Это не его мысль, а Ваша.

caseyryan приписал мне:
Код AS3:

Вообще, исходя из вашей логики, не надо создавать вообще никаких лишних классов. Можно весь код писать в одном полотенце Main и не париться


После чего я приписал ему интерфейсы.

faraday 12.03.2015 01:33

может вообще не стоит использовать классы событий, если нет четкого понимания как и зачем это делать)
передавайте через общую шину событие buyPet, единсвтенное можете расширить Event до datEvent, и уже в data пихаете все что нужно. Мне кажется проблема в первую очередь в архитектуре, но однозначно сказать не могу по этому отрывку кода, но слишком все усложнено и запутано.

callme 12.03.2015 08:29

Цитата:

может вообще не стоит использовать классы событий, если нет четкого понимания как и зачем это делать)
Укажите где я не понимаю как работают события

Цитата:

единсвтенное можете расширить Event до datEvent, и уже в data пихаете все что нужно
Вы описали мой TransportEvent

faraday 12.03.2015 12:28

Дело не в принципе работе событий, а понимании целей их типизации. Вы сами видите что получается сложно и запутанно - это сразу должно настораживать. У transportEvent та же проблема, семантически не отражает своей сути (если это просто dataEvent) . Если пользователь купил собаку, то в системе должно быть сгенерировано что-то типа addPet, это логично что где-то понадобится обрабатывать целый класс событий, а не отдельно рождение кошек, собак, поросят.
Но не видя игры целиком - это опять же мое предположение

caseyryan 12.03.2015 18:37

faraday, вся эта тема, и предыдущая его тема тоже, попахивает каким-то троллингом (кого-то он мне напоминает, из уже неоднократно забаненных на форуме). Чувак либо вообще нифига не понимает и не хочет понимать, либо специально делает вид, что не понимает. Ему уже и так все досконально разжевали что, как и зачем. В итоге вся тема стоит на том же месте, с которого началась.

ZackMercury 12.03.2015 19:13

caseyryan, зато поугарать можно, а то порой тишина зависает, днями никто ничего не постит :D
P.S. Недавно когда кому-то хотел ответить, не помню кому уже, чуть не написал "Akopalipsis, это не вы, случаем?)"... Больно напоминал)

alexcon314 12.03.2015 21:55

// опаздун
посмотрев незамутненным взглядом на топик (и частчно предыдущий), что могу сказать:

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

Типа глянул на листенер и видишь, на какой конкретно тип события он подписан согласно подписке. Т.е. речь идет о чем-то вроде макроса, сниппета или как бишь там оно зовется....автогенерилка кода, короче.

В студии мелкософта нечто подобное имеет место быть, кстати.

А наследование и проч. тут вообще не при чем.

callme 13.03.2015 08:51

У меня было следующее соглашение с самим собой:
  • Если константа находится в классе, который заканчивается на "s", значит в слушатель придет экземпляр класса Event.
  • Если же "s" на конце нет, значит придет экземпляр класса, в котором лежит константа.


То есть когда я пишу
Код AS3:

blabla.addEventListener(TweenEvents.COMPLETE, listener)

то не заглядывая в код "blabla", я могу сразу написать
Код AS3:

function listener(e:Event) {}


а если я пишу
Код AS3:

blabla.addEventListener(TweenEvent.COMPLETE, listener)

то не заглядывая в код "blabla", я могу сразу написать
Код AS3:

function listener(e:TweenEvent) {}


По поводу изначального вопроса, я не знаю правилен ли мой новый подход.
Так как обсуждение целиком свелось к вопросам архитектуры, я наверно буду разбираться сам, т.к. архитектуру на форуме обсуждать долго и трудно.

ZackMercury 13.03.2015 09:43

Зачем это? Это же не логично... TimerEvent.TIMER смотрится уж куда лучше, чем TimerEvents.TIMER.

Добавлено через 23 минуты
К тому же подобный код обещает быть неоднородным.

Добавлено через 26 минут
Вдруг вы в одном месте напишете TimerEvents, а в другом без s, выйдет каша из "новых" и "старых" подходов.

callme 13.03.2015 10:17

Цитата:

Зачем это?
Чтобы класс состоял только из констант. Иначе ему придется наследовать Event, не привнося ничего нового.

Цитата:

Вдруг вы в одном месте напишете TimerEvents, а в другом без s, выйдет каша из "новых" и "старых" подходов.
Тогда исправлю. Редакторы кода с возможностями рефакторинга делают это быстро.

ZackMercury 13.03.2015 10:24

Такой подход не предусматривает пуш-события.
Что, если вы захотите передать вместе с событием новые/обновлённые данные?
Как вы их в Event засунете?

Или вы всё таки превратить код в кашу и там использовать одно, а там другое.
Отсылайте тогда уж DataEvent.

callme 13.03.2015 10:33

Если мне нужно передать какие-то данные в событии, то я создаю кастомное событие в названии которого нет "s" на конце.

Для меня большей кашей кажется
Цитата:

наследовать Event, не привнося ничего нового.

Wolsh 13.03.2015 12:13

ZackMercury, не надо представлять везде DataEvent как панацею. Обнаружьте уже с удивлением, что data у него всего-лишь String, и никакие ссылки на объекты это событие таскать не может.
callme, создать список констант или создать кастомное событие, отличающееся от Event только расширенным списком констант и говорящим названием — технически разницы почти никакой, а в плане организации кода однозначный профит — подписываться на тип из ManEvent и получать в обработчике event:ManEvent — это идеально. Есть еще третий вариант — хранить константы в классе отправителя, но это уже компромисс (Man.I_EAT_MY_DOG). Списки констант (то есть классы в которых ТОЛЬКО списки) хороши, как легкое связующее между системами, которые не должны иметь жесткой связности (например, в MVC Вью не должна импортировать класс Модели, но должна как-то подписаться на ее события. Интерфейс Модели предоставляет Вью геттеры данных, но никак не может описать События. И их (Вью и Модель) приходится связывать либо классами кастомных Событий — то есть и Вью и Модель импортируют в себя одни и те же классы Событий — либо легким списочком строковых констант, используя при этом стандартный Event). Городить списки, которые наоборот только создают неразбериху нет никакого смысла.

callme 13.03.2015 12:58

Wolsh, спасибо. Смирюсь с этим глупым наследованием, все равно класс порождать для констант.

Вопрос по MVC. Мы же во вью все равно завяжемся на классы, в которых константы лежат?

Wolsh 13.03.2015 13:17

Цитата:

Мы же во вью все равно завяжемся на классы, в которых константы лежат?
Не совсем. У Вью может быть свой класс-список, а у Модели свой. Просто значения констант должны совпадать, кроме того у Вью список может быть меньше (скажем, если это маленькое конкретное вью например кол-ва Маны и никакие события кроме изменения Маны его не интересуют). Вью и Модель связаны только строками, а не физически едиными файлами Событий. Еще раз: при использовании кастомного события они должны импортировать один и тот же файл (класс). А строки могут быть записаны где угодно, не обязательно в едином классе-списке. Это просто строки.

callme 13.03.2015 13:23

Wolsh, я так и подумал, но лучше было узнать точно.

Спасибо, эта информация намного интересней, чем ответ на мой изначальный вопрос :)


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

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