< 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 > |