< Day Day Up > |
Now that we're familiar with the basic syntax of inheritance, let's take a high-level look at how inheritance can be used in a real application. Consider a chat application that defines a class, ChatRoom , which handles communication among a group of users. The ChatRoom class defines methods for displaying and sending chat messages and for managing a list of users in the room. Table 6-1 shows the ChatRoom class's property and methods. Table 6-1. ChatRoom class's property and methods
Now suppose that our chat application has multiple room types: some rooms are regular chats and some are "avatar chats." In the avatar chat rooms, each user in the room is represented by a little cartoon character (an "avatar") that can be positioned on screen. When a user in an avatar chat room sends a message to other users, other users see the message both in the normal chat text field and in a cartoon speech bubble next to the sender's avatar. (If you've never seen an avatar chat before, you'll find one example at http:// moock .org/unity/uchatavatar.) To implement our new avatar chat room, we could (but never should!) copy all of the code from ChatRoom into a new class, AvatarChatRoom , and then add the avatar-specific features to that new class. Of course, from then on, any time the code in ChatRoom changed, we'd have to copy the changes to AvatarChatRoom by hand. Across an entire application, that kind of copy-and-paste code maintenance becomes unmanageable in a hurry and should be avoided at all costs. Instead of copying the code from ChatRoom to AvatarChatRoom , we simply make AvatarChatRoom a subclass of ChatRoom . After all, a regular chat room already does most of what an avatar chat room does; the avatar chat room just has the extra responsibility of managing the cartoon representation of each user. The AvatarChatRoom class uses some of the ChatRoom class's methods as-is, just as our simple class B used class A 's x( ) method. For example, to send a message, AvatarChatRoom uses ChatRoom.sendMessage( ) directly. For other tasks (e.g., positioning avatars), the AvatarChatRoom defines its own methods, just as class B added the method y( ) . But for still other tasks (e.g., displaying a message), the AvatarChatRoom needs behavior that differs somewhat from an existing ChatRoom method. For example, when a user's message is received, the AvatarChatRoom class must show the message in a text bubble next to the user's avatar (in addition to displaying it in the "incoming messages" text field, as does the ChatRoom class). That means the AvatarChatRoom class must change what happens when the displayMessage( ) method executes. Known as overriding , changing the behavior of a method is the topic of the next section in this chapter. Table 6-2 shows the AvatarChatRoom 's properties and methods, indicating which members are inherited, which are new, and which are overridden. For another prolonged inheritance example, see Chapter 7. Table 6-2. AvatarChatRoom class's methods and properties
Example 6-1 shows the skeletal code for the ChatRoom and AvatarChatRoom classes. The class properties and implementation details of each class's methods are omitted, allowing us to focus our attention directly on the inheritance structure. In place of method implementations , we use the trace( ) function to display a message describing the method's behavior in the Output panel. Example 6-1. An inheritance example using ChatRoom and AvatarChatRoom// This code must be placed in an external file named ChatRoom.as class ChatRoom { // mx.controls is the package path for the built-in List component. // See Chapter 9 for details on packages. private var userList:mx.controls.List; // Declare the five public methods of the ChatRoom class. public function displayMessage (userID:String, msg:String):Void { trace("Displaying chat message in chat text field."); } public function sendMessage (msg:String):Void { trace("Sending chat message."); } public function onAddUser (userID:String):Void { trace("Adding user to userList."); } public function onRemoveUser (userID:String):Void { trace("Removing user from userList."); } public function onUserChangeName (userID:String, newName:String):Void { trace("Changing name in userList."); } } // This code must be placed in an external file named AvatarChatRoom.as class AvatarChatRoom extends ChatRoom { private var avatars:Array; // Override four of the methods of the ChatRoom class, // excluding sendMessage( ). public function displayMessage (userID:String, msg:String):Void { // AvatarRoom.displayMessage( ) also invokes ChatRoom.displayMessage( ). super.displayMessage(userID, msg); trace("Displaying message in avatar text bubble."); } public function onAddUser (userID:String):Void { // AvatarRoom.onAddUser( ) also invokes ChatRoom.onAddUser( ). super.onAddUser(userID); trace("Creating avatar for new user."); } public function onRemoveUser (userID:String):Void { // AvatarRoom.onRemoveUser( ) also invokes ChatRoom.onRemoveUser( ). super.onRemoveUser(userID) trace("Removing avatar for user."); } public function onUserChangeName (userID:String, newName:String):Void { // AvatarRoom.onUserChangeName( ) also // invokes ChatRoom.onUserChangeName( ). super.onUserChangeName(userID, newName); trace("Changing name on avatar."); } // Declare a new method not present in the ChatRoom class. public function onUserChangePosition (userID:String, newX:Number, newY:Number):Void { trace("Repositioning avatar."); } } You should notice that the code in Example 6-1 declares five methods of the ChatRoom class. The AvatarChatRoom class likewise declares five methods, four of which override methods in the ChatRoom class plus onUserChangePosition( ) , which is new. Let's take a closer look at overriding, its use and implications. |
< Day Day Up > |