Search code examples
actionscript-3eventscoding-styleevent-dispatching

Whats the appropriate form when dispatching events in AS3?


I was wondering what the appropriate form was when creating custom events? Should one create a CustomEvent class, and then create a temporary dispatcher in the function, and dispatch the CustomEvent. or is it better to attempt to create a CustomEventDispatcher class, and create the CustomEvent class as an internal class of that class, eg:

package
{

   public class CustomEventDispatcher extends EventDispatcher
   {
     public function CustomEventDispatcher()
     {
       super(new CustomEvent());
     }

   }
}

class CustomEvent
{
   public function CustomEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
   {
      super(type, bubbles, cancelable)
   }                                               
}

Solution

  • There are two basic questions to answer, when conceiving event mechanics.

    1) How do I create dispatcher instance for my events?

    General options are: extend EventDispatcher, or aggregate dispatcher instance.

    Most basic and common practice (and official docs also state that), is extending EventDispatcher class, thus giving your classes event-dispatching capabilities.

    Pros: simple to implement -- just type extends EventDispatcher, and you are done.

    Cons: you can't extend something else. Apparently, this is the reason why many native classes are EventDispatcher's grandchildren. Just to spare us the trouble, I guess.

    Second general approach is aggregating a dispatcher instance.

    package
    {
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.IEventDispatcher;
    
        public class ClassA implements IEventDispatcher
        {
            private var dispatcher:EventDispatcher;
    
            public function ClassA()
            {
                initialize();
            }
    
            private function initialize():void
            {
                dispatcher = new EventDispatcher(this);
            }
    
            public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
            {
                dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
            }
    
            public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
            {
                dispatcher.removeEventListener(type, listener, useCapture);
            }
    
            public function dispatchEvent(event:Event):Boolean
            {
                return dispatcher.dispatchEvent(event);
            }
    
            public function hasEventListener(type:String):Boolean
            {
                return dispatcher.hasEventListener(type);
            }
    
            public function willTrigger(type:String):Boolean
            {
                return dispatcher.willTrigger(type);
            }
        }
    }
    

    Note: we pass a reference to aggregating class to dispatcher constructor. This is done to make event.target reference your class instance and not the dispatcher instance itself.

    Pros: you are free to extend whatever you like. You may do some tricks with dispatcher hooks like maintaining listeners list or something alike.

    Cons: not as simple as the first approach.

    2) How do I pass custom data with my events?

    General options are: pass data in an event instance, or only use event.target reference in event handler to access some data from source.

    If you choose to access all necessary data through event.target -- no additional work nedded, just cast this reference in event handler to appropriate class.

    If you want to pass some data along with event, you subclass Event, and this class should be publicly visible to the code that handles events, as the answer above states. AS3 is all about strict and strong typing, so why would you resist that?

    Overriding clone() method in an Event subclass is only necessary if you are going to redispatch handled events. The official docs say you must do that every time you create a custom event class, just to be safe.