8.1 The Case for Interfaces

 <  Day Day Up  >  

Suppose we're creating an order-form application with a class, OrderProcessor , that manages the order-filling process. If a customer makes a mistake while filling in the order form, the OrderProcessor class signals an error by broadcasting an event, OrderProcessorEvent . Many classes may want to respond to the event ”one class, OrderUI , may want to display an error message on screen; another class, OrderChat , may want to alert a live support technician; and yet another class, StatsTracker , may want to log the problem to a database for statistics tracking. To respond to the OrderProcessorEvent , each class defines an onOrderError( ) method. When the event occurs, the OrderProcessor class invokes each class's onOrderError( ) method automatically.

That all seems logical enough so far, but what happens if one of the error-event-handling classes fails to define onOrderError( ) ? The event will occur, but the negligent class won't respond. We must guarantee that every class that signs up to receive OrderProcessor events actually defines the onOrderError( ) method.

To make that guarantee, we limit the type of objects that can register to receive events from OrderProcessor . Specifically, if an object wants to receive events from OrderProcessor , it must be an instance of the OrderListener class or an instance of one of OrderListener 's subclasses. The OrderListener class itself implements the onOrderError( ) method in a generic way:

 class OrderListener {   public function onOrderError ( ):Void {     // Generic implementation of   onOrderError( )   , not shown...   } } 

Any class that wishes to receive events from OrderProcessor extends OrderListener and overrides OrderListener.onOrderError( ) , providing some specialized behavior. For example, the following class, StatsTracker , extends OrderListener and overrides onOrderError( ) , providing database-specific behavior:

 class StatsTracker extends OrderListener {   // Override   OrderListener.onOrderError( ).   public function onOrderError ( ) {     // Send problem report to database. Code not shown...   } } 

Back in the OrderProcessor class (the class that broadcasts events), we define a method, addListener( ) , that registers an object to receive events. Only instances of the OrderListener datatype (including its subclasses) can be passed to addListener( ) :

 class OrderProcessor {   public function addListener (ol:OrderListener):Boolean {     // Code here should register   ol   to receive   OrderProcessor   events,     // and return a Boolean value indicating whether registration     // succeeded (code not shown).   } } 

If an object passed to addListener( ) is not of type OrderListener (which also includes instances of any one of its subclasses), the compiler generates a type mismatch error. If the object belongs to an OrderListener subclass that doesn't implement onOrderError( ) , at least the generic OrderListener.onOrderError( ) will execute.

Sounds reasonable, right? Almost. But there's a problem. What if a class wishing to receive events from OrderProcessor already extends another class? For example, suppose the OrderUI class extends MovieClip :

 class OrderUI extends MovieClip {   public function onOrderError ( ) {     // Display problem report on screen, not shown...   } } 

In ActionScript, a single class cannot extend more than one class. The OrderUI class already extends MovieClip, so it can't extend OrderListener . Hence, instances of OrderUI can't register to receive events from OrderProcessor . What we really need in this situation is a way to indicate that OrderUI instances actually belong to two datatypes: OrderUI and OrderListener .

Enter...interfaces!

 <  Day Day Up  >  


Essential ActionScript 2.0
Essential ActionScript 2.0
ISBN: 0596006527
EAN: 2147483647
Year: 2004
Pages: 177
Authors: Colin Moock

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net