| |||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||
Print This Article REALbasic University: Column 084
OOP University: Part EightIn our last lesson, we covered duplicating objects and passing objects as parameters, specifically focusing on how REALbasic treats objects. Today we're going to explore making objects do things.
One, Two, Three... Action!Without the ability to do stuff, objects are limited to simple data storage devices. In other words, they aren't that useful. But give an object the ability to do things and it becomes useful. Combine that with something known as overiding, and you've got incredible power. Let's explore. Giving an object the power to do something is as simple as adding a method to that object's class. Here's a simple example: ![]() Notice we've got a custom class called objectClass which contains a method called doIt. Our pushButton1 talks to the instance of that class called anObject1 and tells it to doIt -- therefore we hear a beep when the button is pushed. Already this is nicely flexible -- pushButton1 doesn't have to know anything about objectClass except that it has a doIt method. We can easily change what doIt does without changing pushButton1:
That's pretty cool, but it's not that powerful (it's little different from just calling a method directly). However, let's imagine we had several kinds of objects, each with their own behavior. Like this: ![]() Now we've got two kinds of doIt behavior. One beeps, the other displays a beep message. The ability to send the same doIt message to different objects is useful. For example, we could add a checkBox control to window1 and label it "Silent." Depending on checkBox1's value (true or false), we could adjust which object we talk to:
However, this isn't especially good programming. If we change the nature of these objects significantly, we'd have to rewrite the code in pushButton1. We want to keep our pushButton1 code as simple as possible. Ideally we want to send a single message regardless of the situation. A more powerful use of objects would be to create a structure like this (the split code pane is showing the code for both checkBox1 and pushButton1): ![]() This simplifies our code by keeping everything in one object, and adding a silent property to our object that indicates whether or not the action should be silent or not. This is an important lesson: A key concept in object-oriented programming is to keep your external code (code not part of an object) as simple and universal as possible. The idea is that changes in your objects shouldn't break external code. For instance, if we wanted to change what happens in the above example when a user clicks pushButton1, we only have to edit our object's class. Our pushButton1 code doesn't change at all. The way you do this is to keep your external code universal. That is, don't make it expect a particular kind of behavior. In our second example, we had pushButton1 deciding whether or not the action should be silent or not. That meant pushButton1 had to know which object did what kind of action. If we later modified those objects, we'd have to make appropriate changes to pushButton1 to compensate. Instead, with the third example, pushButton1 only needs to send a doIt message to the object. The object itself takes care of deciding what kind of action to do.
OverridingThe third example is one way to handle different behaviors within an object, but it's not the most OOP way of doing it. For a more complicated object -- say instead of a simple on/off silent property there were 100 different behaviors -- that way of doing it would be impractical. A better way is to take advantage of an OOP concept called overriding. Overriding is the ability of a subclass to redefine the actions of a parent class (superclass). As a demonstration, let's create two classes called noisyObjectClass and silentObjectClass: ![]() We set the super of silentObjectClass to noisyObjectClass making it a subclass of noisyObjectClass. That means if we don't redefine what doIt does in silentObjectClass, it will have the same behavior as noisyObjectClass. But if we change that behavior for silentObjectClass, then if the object being called is a silentObjectClass, it will do whatever we've defined a silentObjectClass to do. If we set our anObject1 instance to silentObjectClass and run the program, we get a msgBox. If we set it to noisyObjectClass, we get a beep. At first this may seem like we're going backwards: we now have more objects than before (more complicated) and we can no longer dynamically set the behavior (we must define anObject1's type before launch). We could dynamically create the instance instead of having it predefined on window1, but that also adds complexity, and of course we still can't have a checkBox that lets us change the object's behavior on the fly. But those disadvantages only show up because our example is too simple. Overriding just isn't needed. For this kind of project, the second method described earlier would be the best. For a more complicated problem, however, the overriding method is often the best approach. To see the power of this technique we need a more complicated example. We'll cover that in our next lesson when we write a simple, object-oriented drawing program. I guarantee you'll be astonished at how easy it is to create! If you would like the complete REALbasic project files for the projects discussed today, you may download them here. There are three separate projects (doi1.rb, doit2.rb, and doit3.rb) so you can explore the various method demonstrated.
Next WeekWe create SimpleDraw!
LettersThis week we've got a nice letter from Eric:
Thanks, Eric! Indeed I did notice this. I don't know when REAL Software started doing this (I only recently checked out the alpha), but I'm glad they've done it. It will be far less confusing for newbies and of course there's no harm in it being there -- if you don't use it, your app will be just like an RB app created without it. By the way, if you want this functionality now in REALbasic 4.5, you can create your own RB project template to add an App class (or anything else) to all new projects you create. Just create a new project and add in it anything you want. It could be a basic app skeleton you've created, or contain modules or classes you frequently use. Name this project "Default New Project" (no quotes) and save it in the Stationery folder within your REALbasic folder. From then on, whenever you create a new project ("New" from the File menu) that project will be used as a template for the new project. Very cool. From the Stationery help document:
About the Column REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers. Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.) About the Author See the REALbasic University Archives
REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.
| |||||||||||||||||||||||||||