| |||||||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||||||
Print This Article REALbasic University: Column 080
OOP University: Part FourLast time I explained what objects are. Today we're going to look at a key distinction about objects which is rarely discussed. I'm going to do this by explaining the importance of naming classes and objects clearly.
The Importance of NamesBecause of their ability to interherit characteristics, a structure of classes can quickly become enormously complex. (Even our little table of cats is getting complicated!) You have parent classes, children, and grandchildren, each with unique characteristics. Once you start generating instances of the various classes (i.e. mischiefInstance and mayhemInstance in the above), it is easy to confuse yourself. Especially as a beginning OOP student, it is vital that you name your classes and objects in a consistent and logical manner. Drastic problems can come from confusing classes and objects. For example, let's look at this class definition and object use:
Right away, I sense a horrible problem. By naming this class "TVobject," you've just confused yourself. "TVobject" is not an object: it's a class (a structure, definition, or description, depending on how you want to look at it). There's a huge difference (which I'll explain in more detail in the next lesson). You're basically confusing blueprints with the building! (Class = blueprint, object = building). A class defines the structure of an object, but it is not an object itself. A much better way is to define things like this:
I like to use the word "class" in my class definitions just to remind me that it's a class, not an object. For the purposes of this tutorial series, I also use "instance" as part of any object instance. Generally your objects will seem like objects to you and that's not strictly necessary, but if you're just starting to work with objects, it's important to maintain the distinction and get it stuck in your head. What's an instance, you ask? Well, that's a little complicated to get into today: we'll tackle that in the next lesson.
Next WeekWe dive into the prickly topic of instances.
LettersHere's a letter from Thomas Ferrell with a good question about the difference between App and Module:
An excellent question, Tom! Fortunately, it's easily explained. A module is a collection of code. It can contain constants, methods, and properties. All are global: that is, they are available to every other part of your program. The idea of a module is that it should contain routines that are reusable in other programs. For instance, I have a "prefsModule" that contains the basics for the system I use for loading, parsing, and saving preference options. I install this in a program and then I can easily customize it for that specific app. You can export a module by dragging it to a Finder window (REALbasic will create a file with the module's data in it). You can import that module into another program by dragging the module file from the Finder to the current Project window.
Now the "App" thing is a lot more confusing.
Technically, app is a subclass of the Application class. The reason you subclass it is that you can therefore make changes to it (i.e. add properties, events, methods, etc.). By default, all REALbasic applications automatically have an Application object. It's just that you don't see it (there's no interface to it). I think it would be simpler and clearer if REAL Software made it so all new projects included an app class by default. Having it there unused wouldn't hurt anything, but it'd be there when you needed it instead of having to add it manually. Since you can't see the included-by-default Application object, you can't change it. By adding your own subclass, you're free to expand upon the limited capabilities of the normal Application class object. You are correct when you mention that you need to add an app class when you want to handle Apple Events (AppleScripts communicate via Apple Events). There are other benefits as well:
The HandleAppleEvent event is where you parse any Apple Events sent to your program. NewDocument and OpenDocument is where you should put code that is executed when the user tries to create a new document or open an existing document. UnhandledException is for handling exception errors that aren't caught elsewhere in your program. You mention being confused by the fact that App has it's own menu handling system. In truth there's a simple explanation. Normally you put most menu handlers within a window, right? That's because most documents are a window and in true object-oriented design you want the document object (the document window) to handle the menu commands associated with documents. But what if all the windows are closed? If the only place you handle menus is within window objects, there'd be no way for the user to use any menus with all the windows closed! Fortunately, the main command you'd want to use when the windows are closed -- "Quit" -- is handled automatically by REALbasic. So at least the user can quit your program without you doing anything specific to support that. But what about stuff like creating a new file, opening an existing file, or setting preferences? Those might be things a user would like to do without having a document already open. Depending on your application, you might even want to have different preferences for when there's no document open (application preferences) and document-specific settings (document preferences). To illustrate this, I've created a demonstration REALbasic project which you can explore (appdemo.sit). Note that it functions just for display purposes only: no preferences are actually remembered. Here's a flowchart that maps how this application works: ![]() You see, the window menu handlers have first priority. So if there's a window open, the window's filePreferences menu handler is executed. Since menu handlers return false by default, we've got to return true within that handler or else app will also handle the menu event: ![]() In the demo program, try commenting out the return true line above and see what happens! If your window doesn't handle the menu event (or there are no open windows), REALbasic passes the event on to your application object (an instance of your app class, if you created one) and lets it handle it (if it can). This allows you to display one preference dialog for documents (local), and a different one for application settings (global). Note that some menu commands are inappropriate to handle within the application object: the "Close window" command, for instance. If you tried to handle it within the application object, you'd have to first check to see if there are open windows, and second you'd have to figure out which window was the one the user wanted to close. By placing it within the window itself, we greatly simplify things. After all, if the window exists (which it must, for its code to be executed), we know there's at least one window open and the Close command is valid so we can just close the current window. If all the windows are closed, there are no docWindows to detect the Close menu command: the app object doesn't need to do anything (the Close menu command is disabled). Just as the Close window menu handler is inappropriate to place within the app object, it would be silly to put the "new" and "open" handlers within a window. First, if you didn't have code within app and there are no open windows, there'd be no way to create or open a new document! Second, since you therefore must have code within app, why duplicate that menu handler code within a window? Hopefully you can begin to see how these two system divide the workflow. Windows override the app, but app is there if no windows are open. Sometimes one or the other needs to handle the menu command, but there are occasions (such as the Preferences situation) when you want both to function but function slightly differently. If different windows support different menu handlers, the handlers of the window in front (the active window) are the ones that are used.
You might realize that app's Activate and Deactivate events work the same as the menu handling system: if windows are open, those also have Activate and Deactivate events, but if none are open you'd have no way to detect program activation without the app object. Really, the only thing that makes this confusing is that you sometimes create projects with an app class and you sometimes don't. Beginners can't figure out when they need it. In reality you almost always need it, and it doesn't hurt anything if it's there and not used, so why not always include it? Get in the habit of adding an app class to all your projects. You can download appdemo.sit by clicking here. 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.
|
. |
| |||||||||||||||||||||||||||||||