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 094

OOP University: Part Seventeen

Greetings, REALbasic fans! Sorry about the lack of columns the past couple of weeks. It was unplanned, or I would have warned you, but at any rate, my schedule is back to normal. I hope you enjoyed the vacation because it's now back to work!

I've received a number of emails from readers who've appreciated our current "OOP University" focus, so I hope you won't mind if we continue it for a little while longer. There are still a few important aspects of object-oriented programming I'd like to cover.

First, to refresh our minds after our long bout with SuperDraw, we'll do a quick review of the concepts we've learned so far. I want to make sure everyone understands everything.

In the future I'll introduce some new ideas to consider, and we'll explore some tips and suggestions on how to create better object-oriented programs. Finally I have some plans for some example projects which will illustrate many of the ideas we've discussed.

OOP in Review

Modal and Event-Driven Programming

The first couple OOP University lessons pointed the important differences between modal and event-driven programming. This is a topic that is rarely discussed any more (all modern programming is event-driven), but it's vitally important. Event-driven programs are not necessarily object-oriented, but object-oriented programs fit naturally into the event-driven paradigm.

To refresh your memory, in modal programs the program controls the current "mode" and only allows certain commands within that mode. Event-driven programs are sometimes called "user-driven" programs because the program is controlled by the user. Event-driven programs are more difficult to write because the program must be ready any contingency.

However, that makes them ideal for OOP since you can create reusable objects that already incorporate some basic functionality. A perfect example is a window object: add a new window in REALbasic and without any programming by you the window knows how to allow itself to be moved around, expanded, resized, and closed. The basics of how that window is drawn and the user interaction of widgets on that window (resize, collapse, etc.) work without any extra programming by you.

Because OOP makes event-driven programming so much easier, a lot of OOP concepts are wrapped into event-driven programming. People with traditional programming experience often confuse the two, mistaking event-driven aspects for OOP (and vice versa). Just keep in mind that events in themselves have nothing to with objects. Most objects communicate via events (messages), but problems in your application's structure usually have more to do with modal programming than object-oriented design flaws.

Object Basics

Our next few lessons introduced objects, explaining the concept of an object (an arbitrary encapsulated structure), and most importantly, the difference between a class and an object.

Here are the three key things to remember about objects:

  • A class is nothing but a blueprint or template for an object. A good tip is to name your classes with "class" in the name so you don't confuse them with objects (which will cause horrible problems).
  • An object itself exists in memory as an instance -- a copy of the template (class). Instances must be created via the new command. REALbasic handles the destruction of instances on its own: when an object is no longer referred to by any of your code, RB deletes the object and frees the memory.
  • REALbasic lets us access an instance of an object via reference -- simply a property (variable) that's a pointer to the actual structure in memory. That's why you can't simply copy an object via assignment (object1 = object2) since that only copies the pointer, not the object itself.

It's critical you understand these three points, so learn them well.

The Genealogy of Objects

Our OOP lessons continued with giving objects the ability to do things. That's done simply by adding appropriate methods to our classes. But then we complicate the situation by introducing the most important feature of objects: inheritance.

Without inheritance objects wouldn't be much different from modules -- simply a collection of routines. You can reuse a module or method just as you can reuse objects, but the reuse must always be exactly the same. With inheritance, however, an object can inherit the main features of its parent, but add its own unique capabilities.

Even better, with overriding, an object has the ability to redefine the behavior of its parent. Thus two objects can have a draw method but each do different things (the sub-object can define its own version of the draw method and override the parent's method).

This is what gives OOP its power. We get the benefits of code reuse yet still have the ability to customize. The customization doesn't change the parent object at all. Even better, none of our external code changes either!

Encapsulation

This leads us to the next most important aspect of objects: encapsulation. Encapsulation is way of building your object (or object collection) into its own world separate from the rest of your code. This is extremely useful and powerful because it allows you to modify the object without interfering with the outside code, and change outside code without hurting the object. It also makes the object more generic and less specific.

It's important to understand that encapsulation implies incorporating a proprietary data structure to your object. (Objects that don't manipulate or hold data are rather useless.) Your external code (code not part of the object) knows nothing about how the object's data structure is organized. Is it an array? A linked list? A series of properties? Who knows! The external code can only talk to the object via a set of predefined methods. There might be an "addData" method, a "removeData" command, and a "getData" function. But how that data is structured and stored is up to the class.

The best way to understand this is to compare an encapsulated approach to the non-encapsulated way.

Let's pretend we have created a freeform address book application. It holds names, mailing addresses, phone numbers, and other information about contacts. Here's what it looks like:

The interface is simple: a scrollbar along the bottom controls which record is displayed and updates a staticText which tells us which record we're editing. Buttons at the top let us add or delete records.

Obviously our address data needs to be stored in a data structure for the program to manipulate. Since this is a freeform database, we don't need to worry about which piece of data is where: all we need is a way to separate each record of data. So let's say we use an array of a strings: each string will contain a single record of data.

So we add a property to our window:

 theData(0) as string 

Now in our non-encapsulated version, all aspects of the window directly manipulate our data structure (the array). So, for instance, our newRecordButton has this code:

  
theData.append ""
scrollBar1.maximum = uBound(theData)
scrollBar1.value = scrollBar1.maximum

See how it is modifying theData directly? That's bad programming: we want as few elements as possible modifying the data structure. It's also modifying scrollBar1, which could be another problem down the road.

Our ScrollBar1 control has this code:

  
if me.value > 0 and me.value <= uBound(theData) then
// Save changes to record
if oldValue > 0 and oldValue <= uBound(theData) then
theData(oldValue) = dataField.text
end if

dataField.text = theData(me.value)
staticText1.text = "Record " + str(me.value) + " of " + str(me.maximum)
oldValue = me.value
end if

As we continue to add features, the code becomes more complex. DeleteRecordButton needs to modify theData also, and we've created multiple elements that interact and each manipulate the data structure directly.

Sure, this will work... for now. The problems come in the future, when you decide to add more features (like a "Find" command) and perhaps decide to modify your data structure. Then your entire program breaks -- all the code between your interface and data structure must be rewritten.

In Detail

You've heard code described as "spaghetti" code? Well, I think a better analogy is untangling Christmas tree lights -- what a mess that can be!

Yet that's exactly what happens in a complicated program. As element A modifies element B which modifies element C which modifies elements A and D, and element D changes element E and F, which each change elements D and B, it starts to get ugly. While you're deep within the program you can probably follow this trail, but a new programmer, or yourself coming back to this program after a year's absence, will find the maze of code bewildering. Yet to understand how a program works, you must be able to trace the program's execution: what will happen during each step of the program's execution?

Objects don't eliminate spaghetti code, but they make it easier to avoid if you design correctly. Encapsulation forces you to design a program where the data structure is modified by only a few set routines instead of dozens of pieces of code. That makes it much easier to track down behavior and see what is going on.

If this is written in an encapsulated format, however, it's far easier to update in the future because the interface code simply sends messages to the data object.

Let's rewrite this app by making a subclass of the ScrollBar control. We'll make it Data Central Command and only allow it to manipulate the data structure. Add a class (File menu, "New Class") called scrollClass with a super of ScrollBar.

Our scrollClass class will contain routines (methods) for manipulating the data structure: no external code will know anything about the structure or be able to manipulate it:

As you can see, we've added a number items to the class. We've added a new event (initialize), which happens when the control opens. We'll need that in order to set links to the editField and staticText objects that scrollClass manipulates.

Within ScrollBar1 (which is now a scrollClass object), we put this code in the initialize event:

  
// Very important!
// We must link scrollbar to other elements!
me.dField = dataField
me.label = staticText1

This lets our object talk to the appropriate elements of window1. It's really the most complicated part of the program, and as you can see, it's not that complicated. You just must remember to properly initialize scrollBar1 before using it.

Once initialized, scrollBar1 controls everything. Look how much simpler the window1 code becomes. The action event of newRecordButton is now this:

  
scrollBar1.addRecord

DeleteRecordButton looks like this:

  
scrollBar1.deleteRecord

See how much simpler our external code becomes? Now we can modify scrollClass as much as we want but we'll never have to change that external code.

Of course to properly finish this class we'd need to add routines to load and save the data to a file, as well as a folderItem property. Then window1's file menu commands would just send a message to scrollClass to open or save the file.

I hope this example makes the importance of encapsulation a little clearer. While I didn't actually finish this address book application, you can look at the shells of the app if you like. I'm including both versions (non-encapsulated and encapsulated) of the project file.

Next Week

We'll finish our OOP review and move on to a few new ideas you should understand.

News

Recently REAL Software announced news we've been anticipating for some time: REALbasic is now available for the Microsoft Windows platform! The basic product is US$99.99 while the professional version (normally US$399.99) has an introductory price of US$299.95 until May 23, 2003.

You can read the full announcement here.

REAL Software have also updated the Mac product, releasing the free 5.1 update. This update fixes problems and significantly speeds up compilation time -- I highly recommend you go download this latest version immediately! This version also includes a handy "4.5 to 5.x" project converter PDF document, which details some of the changes 5.x brings and how to ensure your old projects work in the new compiler.

Letters

Our letter this week comes from Joe Rice, who writes:

First of all, thanks for your previous help. Been great to have an experienced user to answer my questions.

Now for my problem. I'm fairly new to RB, and thought i'd make a calculator to get a feel for the maths side of programming. I got everything working well, except for when I try to put in numbers with a decimal point.

This is because integers are whole numbers and ignore anything after a decimal point, so I was wondering how to convert a string from a text box to a number that could be used say, in addition that supports decimal points.

At the moment, my code for addition is:

  
ValueX=Val(XValue.text)
ValueY=Val(YValue.text)

Answer.text=Str(XValue+YValue)

That is basically it. Please help me with this as it is bugging the hell out of me.

Cheers!

Joe

I've actually thought of doing a calculator as an RBU project, though I don't know when that will be. It's a simple but good project in that it demonstrates many useful techniques.

The problem you are experiencing is extremely common. The mistake you are making is using integers instead of doubles. You should define your variables as double like this:

  
dim ValueX, ValueY as double

The double data type supports fractions (numbers with a decimal point). This won't hurt anything if the typed in number doesn't include a decimal point, but if it does, the number will convert correctly with the val() function. That should solve your main problem.

Going the other way, number to string, you may find that str() trims the numbers past the decimal point too soon. For better control over the conversion, use the format() command instead. The format() function will also let you work with percentages, currency, and even automatically add commas for larger numbers.

I hope this helps!


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