REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 095

OOP University: Part Nineteen

Last week we started a review of OOP concepts we've covered so far, as I want refresh everyone's memories and make sure we're all on the same page after the SuperDraw series. I reminded everyone of the importance of encapsulation. Today we'll continue by examining what SuperDraw taught us.

Isa

One of the most powerful features of OOP is the isa operator. You'll remember we used that as part of SuperDraw when we detected which object was passed. This is a side benefit of inheritance. Because a sub-object is still, technically, a member of its parent class, you can pass a generic object as a parameter in a routine.

For example, if you have a main class of animalClass and sub-classes of catClass and dogClass, you could have a routine like this:

  
sub aRoutine(theAnimal as animalClass)
if theAnimal isa catObject then
// bla bla bla
elseif theAnimal isa dogObject then
// bla bla bla
elseif... // etc.
end sub

This is powerful because the routine is not fixed to only operate on cat objects, but can operate on any animal. The isa operator gives our routine the ability to figure out exactly which animal we're dealing with, if we need that. (Remember, if the routine is only modifying or examining common animal properties, there's no need to detect the animal species.)

Don't forget about isa -- it's an important concept to keep in mind when you're designing your OO application. Many times you can simplify your design by using the isa operator.

Building an OOP Application

As part of OOP University, we built a program called SuperDraw, which was an object-oriented drawing program. If you remember, this project started out as SimpleDraw, and we used the OO-basis to show how easy it was to expand and enhance the program into the much more capable SuperDraw.

Why do mention this? Because it's important. You see, the benefits of OOP are not that it's easier to program. Especially if you're not familiar with objects, OOP can be more difficult. In fact, to built an object-oriented application properly requires significant planning and design.

No, the advantage of OOP comes when it is time to rebuild, rewrite, enhance, or debug your program. Let me repeat that loud and clear:

The advantage of OOP comes when it is time to rebuild, rewrite, enhance, or debug your program.

Got that? What that means is that if you're writing a "one-off" program -- a simple program designed to do one thing for one time only -- you're probably wasting effort trying to built it with objects.

For example, earlier this year my accountant needed certain kinds of financial data from me for REALbasic Developer magazine. This info was difficult to glean from the database as I needed to do certain math functions on various data (I was forced to break out the amounts of undelivered issues and shipping costs as separate items as some amounts are tax deferred and some not). So I wrote a "one-off" program that simply analyzed the raw data and extracted the info I needed, producing a tab-delimited report I could take into a spreadsheet for further calculations. Since this was a program I was going to only use once (or at most just once a year), I didn't worry about it being a proper object-oriented design.

Where OOP pays off is on projects that will be around for a long time. Those kinds of programs you tend to expand, rewrite, and add functionalty, and OOP makes doing that much, much easier. As we saw with SuperDraw, once we'd built the basic OO app, it was fairly simple to add new objects and new capabilities. But creating that initial OO app did require some planning about the direction we'd take.

I think of OOP and traditional programming as being opposite triangles of development, like this:

Traditional programming requires less setup and planning and thus can be easier to get to an initial running program (not finished, but running). An OO program means planning how your objects will work together and writing all the classes. Since those classes interact, sometimes it's a while before your app runs -- but when it does, it's almost finished. And, of course, modifying or enhancing the behaviors of the objects is easy.

Object-oriented programs are also more difficult to write initially because you should create objects with reuse in mind. This means lots of thinking ahead, of future projects, and sometimes it means "over-writing" the objects -- making them more robust, powerful, and generic than you need for the current application. But a smart programmer will realize that a few extra minutes today will mean faster development of future projects.

Here's a quick, very simple example. Let's say you're writing a program and you realize you need a text field that only accepts numbers (a numbers-only editField). This is the only place you need it in the entire program, so your first instinct is just to write this within that particular editField. But hold on: surely this would be a useful class for other programs you'll write.

Here are three ways you could solve the "numbers-only" problem:

  • Code the editField directly.
  • Create a numbers-only editField sub-class that you can reuse.
  • Create a powerful, flexible editField sub-class that includes a system of settings where you can tell that object what kinds of input to allow. For instance, sometimes you might need to allow a period to be typed in case the number is a decimal. Other times you might want a particular pattern. A really powerful class could allow you to establish a pattern of allowable digits and letters. Then this single class could be reused in many programs to allow for number input, date input, time input, currency input, registration number input, etc.

As you can see, each of these takes a little more time to create than the previous one. However, they are also more powerful and will save you time in the future. It's up to you to decide if it's better to do something quicker today or save yourself time in the future.

I get emails and talk to RB programmers who sometimes feel frustrated that their programs are not object-oriented. Some aren't even sure what that means, others just assume that OOP is better and their programs need to be object-oriented. My point is that not all programs need to be object-oriented, and that OO programs do require more initial design effort, something that beginners find difficult.

The key to OOP is planning. What we're going to cover next is some ideas on how to better design and plan your apps to make them object-oriented. We'll examine several typical programs and compare the OO and non-OO versions.

Next Week

Designing object-oriented programs.

Letters

Today we've got a letter from Myron Tribus, who wants to know about passing strings. He writes:

I have already written two tb program that work and am starting a third. I previously programmed in TrueBASIC from Dartmouth since about 1964, when it started. This probably is a handicap! Anyway, in TrueBASIC I can call a subroutine and hand off to it a string, say. However, if I retrieve a file and put it into a string, say S, and now I want to do some operations on this string as a result of pressing another button, how do I transfer S to the new object? The virtue of object oriented programming is that each element is independent. How do I share information between objects? I have thought of putting the string into a list box where it is available to other objects but there should be a better way.

Your tutorials have been most helpful.

Thanks for the question, Myron. I think I see your trouble. It has more to do with scope than with anything particular about strings.

Scope is a concept that confuses newbies tremendously. Basically, variables are only "alive" or visible, within certain sections of your code. In object-oriented programming, that could mean only within certain objects. For example, if window1 has a property of theString, then the variable theString won't exist in other routines outside of that window. It is part of window1 and only visible to objects and code inside window1.

This is known as a local variable. That is, it is visible only to code around it. You can get even more local than a window's properties. A variable you define as part of a subroutine is local to that subroutine: other code cannot access that variable. It doesn't exist to them.

Global variables are properties that exist to your entire application. Any part of your application can see and access those.

So why the difference? Why bother to have such a confusing mess where some variables are local to a subroutine, some local to an object (like a window), and others global?

There are several answers to this question. For one, global variables are not as memory efficient as local variables. Local variables only exist while a routine is running or an object is alive. That's efficient because if a routine is never executed, no memory space is wasted allocating RAM for that variable that will never be used.

Another reason why local variables can be good is that they help force you to design your program better. It is logical, for example, for a window that contains a file's content to contain a data structure with that data in it. If you have multiple windows, each is a separate object containing its own set of variables with its own data. If you instead put the data into a global variable, you'd either be forced to only allow one file at a time to be opened (since there's only one global variable there's only enough space for one file's data at a time), or you'd have to somehow dynamically add data space to your global variable (i.e. via an array). That could get really complicated. For instance, if the user has nine files open and closes the middle one, you'd have to look at your global data structure and delete the middle one. That's a lot of data management you're doing and for what? You don't get any benefit except allowing one window to see the contents of another. For most multi-document programs that's not necessary or even desirable. (If you open two word processing files, do you ever want or need edits to Document A effecting Document B?)

In your situation, you've got several choices.

One, you can make s (the string containing your file's content) global, thereby allowing access by any part of your program. That would mean you don't have to move the data around at all.

Two, you could pass the data from one part of the program to another. For instance, if window1 has the data and you know window2 needs the same data, create a property of window2 that will contain the data and assign it like this:

  
window2.theString = s

This code would be somewhere inside window1, and it would copy the string to window2.

You could also pass the data to a procedure or function that's a part of another window or another portion of your program:

  
DoSomethingWithTheString(s)

A third way is a little more complicated, but powerful. You could simply access the data of another object via REALbasic's dot syntax. We've already done that in the above examples. Window2 can "see" the variable s that's part of window1 if you tell the compiler that it's part of window1:

  
dim temp as string

temp = window1.s
// bla bla bla

Here we've copied window1's s variable to a routine's temp local variable. Temp will only exist within this routine, but while it exists, it contains the contents of the file, and you can do whatever you need with it.

But say you've got multiple windows created dynamically as the program runs. This happens, for instance, if the user opens multiple files in your program. Now you don't know which one contains the data you want. Since there's more than one window, it may not be window1. (Your program has dynamically created copies of window1, but referring programmatically [in code] to window1 will only point to the first one.)

The solution to this is to create a property that points to the proper window. For example, window2 could contain this:

  
parentWindow as window1

Now window2 can refer to parentWindow.s instead of window1.s. But for this to work, you must make sure that parentWindow is valid (not nil). Otherwise your program will crash.

ParentWindow will always be nil initially, until you change it by pointing it to a window1.

This gets a little complicated, but it's an extremely common way of allowing dynamic objects to work together as a group. Object1 knows about object2 via a link -- a property that points to the second object.

Here's a practical example. Say you've got a text editing app. You have a find/replace dialog box. You could pass the entire text file to the dialog box and have it return the modified text. But that's wasting a lot memory since there'd be two copies of the text.

A more efficient way is to pass a reference to the parent window (the text document) or a reference to the data object to the dialog and allow it to work directly on the data. Then only a reference is passed, not a duplicate of all the text.

The key is initializing the pointer variable: it must be valid and point to the correct parent object, or this fails. Code that works on this must be sure to check that the pointer is valid before attempting to work with that data. Like I said, a little more complicated, but more efficient than a simple global variable.

This is a complex subject. I hope I helped clarify it a little for you.

I should also add something that's mentioned frequently but still escapes many beginners: in REALbasic, to create a global variable, simply add it as a property to a module (File menu, "New Module"). Any constant, method, or property that's part of a module is always global, available to any other part of your program.


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
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

Email This Article - Comment On This Article

.

Reader Specials

Server Racks Online:
Apple Xserve CompatibleServer Racks and Universal Network Racks
42U KVM Switch Solutions:
High-End Mac and Multi-Platform KVM Matrix switching solutions!
Digital Camera Online:
Great prices on Digital Cameras and accessories!
KVM Switches Online:
Great prices on Mac KVM Switches from the leading manufacturers!
LCD Monitors Online:
Great prices on LCD Monitors from the leading manufacturers!
LCD Projectors Online:
Shop online for LCD Projectors from the leading manufacturers!
USB 2.0 Online:
Great prices on USB 2.0 products from the leading manufacturers

Serious Business Software:
Accounting, Sales, Inventory, CRM, Shipping, Payroll & more!

KVM Switch solutions for MACs:
DAXTEN is a KVM switch, KVM extender and monitor splitter specialist for PC, SUN and MAC applications from name brand manufacturers - offices worldwide.

The "Think Different Store: The iPod Accessories Store - iPod cases, iPod mini, iPod photo, speakers, itrip, inMotion, Soundstage and all other iPod accessories

Earn Cash with the ThinkDifferent Store Affiliates Program

Need A Web Site?
Applelinks Web Hosting Starting at 19.95 a Month

iTunes_RGB_9mm

.

iTunes_RGB_9mm

Cool Mac Gear


iPod 1G-2G
iPod 3G
iPod 4G
iPod Mini
PowerBook-iBook
Keyboard Skins
Garageband