BUY THIS BOOK

Safari Books Online

What is this?

Looking to Reprint this content?


REALBasic: TDG
REALBasic: TDG, Second Edition

By Matt Neuburg

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: The Workspace
This chapter introduces the REALbasic workspace, also called the IDE (for integrated development environment; see Section P.2 in the the preface). We'll tour the IDE's various windows and talk about what they do and how you work with them. By way of illustration, we'll actually build a working application. So you might want to follow along on your computer, with REALbasic running. You'll discover that writing an application with REALbasic can be almost effortless, involving just a few swift, easy moves on your part, and that the IDE is extremely simple, consisting of a very small number of windows and menus. (Figure 1-1 shows the REALbasic IDE in action. Don't worry, this is not the working application we'll be building in this chapter! If you're curious, it's my Durak card-playing program, which you can download from my web site.)
Figure 1-1: Working in the REALbasic IDE
When you start up REALbasic by opening it from the Finder, two windows occupy the center of your screen, as shown in Figure 1-2.
Figure 1-2: A new empty project
The rear window is the Project Window. If you close the Project Window, or if you don't see it, you can open it and bring it to the front by choosing Window Project. The Project Window represents your project, and provides access to its components.
What is a project? Simply put, it's a REALbasic document file on disk. Every application that you create with REALbasic is represented by, and will ultimately be generated from, a single REALbasic project document. The project file is not, itself, the application you're planning on creating; it's a much smaller file where you tell REALbasic all about that application. With REALbasic, you work on a project file; when it's ready, you tell REALbasic to generate (or
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Project Window
When you start up REALbasic by opening it from the Finder, two windows occupy the center of your screen, as shown in Figure 1-2.
Figure 1-2: A new empty project
The rear window is the Project Window. If you close the Project Window, or if you don't see it, you can open it and bring it to the front by choosing Window Project. The Project Window represents your project, and provides access to its components.
What is a project? Simply put, it's a REALbasic document file on disk. Every application that you create with REALbasic is represented by, and will ultimately be generated from, a single REALbasic project document. The project file is not, itself, the application you're planning on creating; it's a much smaller file where you tell REALbasic all about that application. With REALbasic, you work on a project file; when it's ready, you tell REALbasic to generate (or build) your application from it.
In Figure 1-2, REALbasic was started up directly from the Finder without specifying an existing project file, so a new project has been created automatically. No project file exists yet; that's why the Project Window's title is Untitled. Once the project is saved to disk, by choosing File Save, the Project Window will take on the name assigned to the project file. (For instance, one might save this project as My First Project.) A project file on disk works like any document file: it can be opened by choosing File Open within REALbasic, or it can be opened from the Finder, which will also start up REALbasic if necessary; and you can create a new project by choosing File New. To keep things simple, exactly one project can be open at a time; when REALbasic is running, and you open a project or create a new one, the currently open project will be closed (REALbasic will offer to save it first).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Editing Windows
It may surprise you to learn at this point that, although you haven't edited your new project at all, you can already build a working application. To do so, you'll probably wish to save the project file if you haven't already; then choose File Build Application, specify a name for the built application in the dialog (or just accept the default name, AppName), and click the Build button. Note that the application will be created in the same folder as your project file, and that you cannot elect to create it anywhere else. (If you don't save the project file before building, the application is created in the same folder as REALbasic.) Then, in the Finder, look in that folder; lo and behold, there's now an application called AppName (or whatever you decided to name it). Open this icon from the Finder to run the application.
The Build Application dialog does not warn you before replacing an existing file with the specified name when you hit the Build button (though it will refuse to replace a running application). There's a good reason for this: you can expect to build the same application many times in the course of development, and it would drive you mad to have to jump each time through any more hoops than you must do already (indeed, in time you'll probably resent even the Build Application dialog). So take care when specifying the name of an existing file, as REALbasic will happily (and silently) overwrite it.
One might be tempted to dismiss the resulting application as useless—which, indeed, it is. It does nothing. It consists entirely of an empty window; click the window's go-away box, and it consists of nothing at all. But although it has no functionality, this application is hardly inconsiderable. The application puts up a window; the window redraws itself properly when covered and uncovered by another application's window; the window can be moved or dismissed; the application runs, harmlessly, among the other applications on your computer, and you can switch between applications as usual; the application has two menus, a File menu and an Edit menu; and the File menu contains a Quit item, which works, either by choosing it manually or by hitting Command-Q. (On Mac OS X, the Quit item is in the system's application menu; for example, if your application is called AppName, then there's a Quit AppName item in the AppName menu.)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Adding Functionality
Thus far, we've concentrated on our application's physical appearance; we've caused the application to have a window containing a button. When the application runs, you can press the button, but nothing happens. We haven't given the button any functionality; indeed, we haven't given any part of our application any functionality. The application runs, and it looks nice, but aside from the functionality automatically built in by the REALbasic framework, such as the ability to quit, it doesn't do anything.
To give our application more functionality, we write code. As explained in the Preface, Section P.2, REALbasic is object-oriented, so that writing code consists not merely of dictating actions that the application should perform, but of associating those actions with the appropriate objects. The integrated nature of the IDE, and the intuitive, natural structure of REALbasic's object model, make this easy to do.
Suppose we want our application to react when the user presses the button in the window; let's say we want it to beep and put up a dialog box that says: "Sorry, this application doesn't do much!" The way to code this action is as follows :
beep
msgBox "Sorry, this application doesn't do much!"
Since this action is to be a response to pressing the button, it makes sense for the object with which we shall associate the code to be the button. To edit code associated with the button, double-click the button in its Window Editor. A new window opens; it is a Code Editor (see Figure 1-7).
Figure 1-7: A Code Editor
The Code Editor in Figure 1-7, as its titlebar says, belongs to our Window1 window. Each window, class, and module listed in the Project Window has a Code Editor of its own. The association of code with an entity is performed by entering the code in that particular entity's Code Editor. In this way, REALbasic forces your code into an object-oriented organization, and clarifies that organization physically: all the code associated with a particular object is bundled into that object's Code Editor, and that Code Editor is accessed by way of the object's physical avatar—either its Window Editor (in the case of a window), or its listing in the Project Window.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
How the Three Editors Relate
We've seen that the IDE provides three ways of editing an interface element such as a window or a control: the Properties Window, the Window Editor, and the Code Editor. In this section, we'll pause to clarify the relationship between them. Figure 1-10 provides a schematization of the relationship between the three editors and the values of object properties. The rest of this section explains in words what the figure is trying to show in pictures.
Figure 1-10: How the three editors control object properties
The Window Editor and the Properties Window edit exactly the same thing—an entity's predefined properties. They simply visualize those properties in two different ways. The Window Editor offers a physical representation of a subset of the very same information that is represented through name-value pairs in the Properties Window.
Consider, for instance, a window that contains a button. In the window's Window Editor, it is evident that the window has a certain size and a certain title. But this information is also present among the values in the window's Properties Window, as its Width, Height, and Title properties. Similarly, the Window Editor shows the button as having a certain position and size, and a certain caption in a certain font; and again, this same information is also represented in the values in the button's Properties Window, as its Left, Top, Width, Height, Caption, and Font properties. But the Properties Window also lists some properties that have no physical representation in the Window Editor, or which cannot be edited there, such as the window's Placement property, or the button's Enabled property.
When you set the values of an object's properties in the Window Editor or the Properties Window , what you're setting are the values that those properties will have just at the moment the object first comes into being in the running application. For example, when you start up our sample application with the window containing a button, the window appears immediately, and that's the moment those objects first come into being, so that's the moment when the properties of those objects take on the values you previously set in the Window Editor and the Properties Window.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Testing Without Building
The only way to know whether your application works as desired is to test what happens when you run it. Even a simple application may call for extensive testing, if only because what happens as your application runs depends not only upon your code but also on what the user does at any given moment. Also, you may find that the easiest way to develop your application is to "grow" it gradually, first implementing some small part of its functionality, testing to make sure it's working properly, then adding some more functionality, and so on. So doubtless you'll want to experiment constantly to make sure whatever code you've written so far is behaving correctly, and that it can handle whatever contingencies the user may throw at it. You'll test your application, then edit the project to cope with problems or to add functionality, then test again, then edit again, over and over as the application takes shape and becomes increasingly robust.
Up to now, we've been testing our application by building it and then running the built application from the Finder. If this were the only way to test, the edit-run-edit cycle would be rather clumsy. In actual fact, though, you mostly won't have to build the application in order to test it; instead, you'll run it in a kind of simulated state within REALbasic itself. To do this, simply choose Debug Run. Your project is now running in the IDE. The application's window and menubar appear, and you can interact with it just as you would the genuine built application. When you quit the running project, you fall back into REALbasic's editing environment.
Running the project in the IDE is in some ways better and in some ways worse than running the genuine built application. It is certainly much quicker and more convenient to edit your project, run it in the IDE, test, and quit back into REALbasic, than it is to have to juggle three processes at once (REALbasic, the Finder, and the built application). Also, running in the IDE has the decided advantage that if an error occurs, you fall back into the IDE, which shows you what the error was; whereas, if an error occurs in the built application, it may quit, or crash, leaving you none the wiser as to what went wrong. On the other hand, although running in the IDE is a good simulation of how your built application will behave, it is just a simulation; the only truly reliable way to test your application is to build it and run it.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Online Help
REALbasic provides online help through the Language Reference window; to see it, choose Help Language Reference. The online help consists of pages devoted to the elements of the REALbasic language, one page per element; in essence it is a presentation of REALbasic's reference manual, also available in PDF and printed form. (This results in some anomalies, such as the online help's references to pictures it can't display.) The online help's importance won't really emerge until you start working with the language, beginning in the next chapter; but since we're describing the IDE, this is the place to discuss the online help.
The Language Reference window is organized rather like a Code Editor. Down the left side runs a browser listing the names of the REALbasic language's operators, keywords, built-in classes, global methods, and error message types. Clicking a browser listing shows the corresponding page of information on the right side of the window. The browser listing can be shown in two ways: if you click the Alpha button at the top of the browser, you see all the pages listed alphabetically; if you click the Theme button, you see them grouped thematically. The window works like a web browser in other ways as well; pages contain hyperlinks to related pages, and there are Back and Forward buttons for moving among the pages you've visited, as in a Code Editor window. Example code (shown by a dotted rectangular outline) can be copied elsewhere, such as into a Code Editor, by drag-and-drop.
One of the Language Reference window's most important features is its ability to search. The text field at the top uses intelligent typeahead, which works just as in a Code Editor. The button to its right alternates between Search and Go, depending on whether you hold the down the Option key. (Which of the two possibilities is represented by the button's default state depends upon a setting in the Preferences dialog.) Pressing Search reduces the browser listing on the left to just those pages that might be relevant to what's in the text field. Pressing Go shows the page named by what's in the text field, without reducing the browser listing.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Shortcuts
This completes the tour of the REALbasic workspace. What follows is a summary of nonobvious shortcuts for navigating and working in the IDE. Some of them we've met earlier in the chapter; others are new.
To open a window's Window Editor
If you're in the Project Window, double-click the window's listing; or select the window's listing and hit Return; or bring up the contextual menu associated with the window's listing and choose Edit. If you're in the window's Code Editor, hit Option-Tab, or press the first button at the bottom of the Code Editor window.
To add a control to a Window Editor
Drag the control's icon from the Tools Window into the Project Window, or copy-and-paste or duplicate an existing control. (In Chapter 3, we will learn that there is another way: you can drag a class listing from the Project Window into the Window Editor.)
In a Window Editor, to select the next control
Hit Tab. This can be particularly useful when controls obscure one another or are otherwise difficult to select; it works even when the control is located beyond the bounds of the Window Editor and is therefore invisible. It is helpful also as a way of changing what object's properties show up in the Properties Window.
In a Window Editor, while positioning a control, to disable "intelligent" alignment
Hold Command while dragging the control, or position it using the Properties Window.
In the Properties Window, to "set" a string or number value
Hit Return or Enter.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: The Basic Language
In Chapter 1 you wrote a working application with REALbasic, where the user can press a button and, in response, hears a beep and sees a little dialog. Just possibly, however, you'd like your application to do a little more than this when the user presses that button. In that case, you're going to need to write some code, using REALbasic's programming language, which (as the name implies) is a form of Basic. In this chapter, you'll start to learn REALbasic's Basic; in fact, you'll learn all there is to know about it, except for the bits having to do with object-orientation. Those bits come in Chapter 3 and Chapter 4.
The name "Basic" is applied to any programming language that descends from the original BASIC (Beginner's All-purpose Symbolic Instruction Code) invented in 1964 by Thomas Kurtz and the late John Kemeny. College courses about computers were new in those days, and BASIC was one of the first computer languages deliberately designed for teaching nonspecialist beginners to program. It gained popularity, in a somewhat bastardized form, in the mid-1970s when it was built in to early personal computers; these computers had tiny memories, but such wizards as Steve Wozniak and Bill Gates ingeniously constructed even tinier BASIC interpreters for them.
The original BASIC was characterized by a small, simple, English-like vocabulary and syntax, surrendering elegance and even convenience to let the user write acceptable code immediately, to shield him from details of implementation, and to protect him from his own mistakes. Even today, Basic dialects typically maintain this traditional spirit of simplicity and safety; but they generally add modern features such as structured programming, and often object-orientation. REALbasic is no exception.
It could, perhaps, be argued that the fact that REALbasic uses a Basic dialect is neither here nor there. The important aspects of REALbasic are those described in the Preface: its application framework, its object model, and its IDE. The language in which you write code could thus have been just about any computer language capable of expressing and accessing the object model, and REALbasic might easily have ended up as REALc, REALscheme, or REALjavaScript—and there are probably users who wish it had! Basic was probably chosen for its simplicity and its universality, and to give users of a certain Windows programming environment an easy migration path.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Lines and Commands
When speaking of code, we use the term line to mean a stretch of text delimited by return characters. In the Code Editor, the return character is invisible, but its effects are evident, because each line really does occupy exactly one physical line. Unlike an ordinary word processor, the code does not "wrap" when it reaches the right edge of the window; a new line begins only when a return character is encountered. (Unlike many other dialects of Basic, REALbasic does not permit you to put more than one line of code onto a physical line, or to split a line into more than one physical line.)
REALbasic is an "imperative" language, meaning that code is composed of commands. Each command appears as a separate line in its handler. The lines of code in a handler represent a sequence of commands, meaning that unless the commands themselves instruct otherwise (and we shall see later in this chapter how they can do this) the lines are executed successively, from top to bottom.
Recall, for instance, our handler from Chapter 1:
beep
msgBox "Sorry, this application doesn't do much!"
The way these words are arranged into lines is significant in two ways. First, the lines appear in a particular order, which means they are to be executed in that order—first we make a beeping noise, then we put up a dialog. Second, there are two lines, because there are two commands; it would be illegal to combine the two commands into one line, like this:
beep msgBox "Sorry, this application doesn't do much!" // error: Unexpected token
            
The error is because you can't have two commands on one line.
It would also be illegal to split up the two lines into three, like this:
beep
msgBox // error: Unexpected end of line
"Sorry, this application doesn't do much!" // another error: Statement expected
            
Here, the first error arises because the msgBox command requires more information—okay, says REALbasic, I should put up a dialog, but what should the dialog say? That information belongs to the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Variables and Constants
A primary feature of any computer language is its ability to associate a name with a value. In this section, we discuss a particular type of name-value association called a variable.
In REALbasic, as in many computer languages, the association of a name with a value is performed in code by means of the = operator. An operator is a symbol, as in arithmetic, used to combine two values or to change a single value. The name goes on the left side of the = operator, the value on the right. For example, we might say:
myBirthYear = 1954
thisYear = 2001
These are not statements of fact; they are commands. Each line tells the computer to associate with the name on the left side the value on the right. So, as a result of executing these commands, the name myBirthYear ends up having associated with it the numeric value 1954, and the name thisYear ends up having associated with it with the numeric value 2001. Such a command, one whose main verb is the = operator, is called an assignment.
Once a name and a value have been associated, the name can be used to denote the value. For example, having executed the preceding statements, we could then perform an arithmetic calculation:
myAge = thisYear - myBirthYear
This command involves the subtraction operator, which, as one might expect, causes a subtraction to be performed. Here's how REALbasic responds to this command: first, the values associated with the names on the right side are retrieved; then, those values are arithmetically combined (in accordance with the subtraction operator) to give a value for the whole right side; and finally, that value is assigned to the name on the left side. As a result of executing this line in combination with the previous two, the name myAge ends up having associated with it the number 47.
It is perfectly permissible, having assigned a value to a name, to assign a different value to that same name. For instance, in our previous example we got the wrong answer (I'm actually 46), so we could correct it by giving the following command:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Subroutines
A handler is a sort of pigeonhole in a Code Editor for containing code. The code constituting any one handler must consist of exactly one subroutine. A subroutine is a block of code that can be called (told to execute) by some other piece of code, or by REALbasic itself. Every subroutine is of one of two types: it is either a procedure or a function . There are some formal differences between procedures and functions that will be described in this section. The really important difference between them, though, is that a function ends by handing back a result to the code that called it, and a procedure does not; a function is said to return a value. In a broad sense, calling a procedure is like giving a command, whereas calling a function is like asking a question, the answer to which is the value returned.
A procedure and a function are formally distinguished from one another by the lines with which they begin and end. You will never need to type such lines, however; REALbasic always inserts them for you, both when a handler is supplied automatically and when you create one. You can see this in any project by examining the handlers in the Events category of the default window; for example, the window's Open event handler is already declared as a procedure, and its CancelClose event handler is already declared as a function.
A procedure begins and ends with these lines:
Sub 
HandlerName()
    // ... commands go here ...
End Sub
A function begins and ends with these lines:
Function 
HandlerName() As 
ReturnType
    // ... commands go here ...
End Function
In both cases, the first line is the subroutine declaration. It gives the name of the subroutine, which will almost always be the name of the handler. (The "almost" is because of menu event handlers, discussed in Chapter 6.) It states, through the use of
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Regulating Flow
Nothing is so characteristic of computer code as its capacity to determine, even as the code is executing, the path that future execution should take. Making the path of execution, or flow , deviate from the normal top-to-bottom sequence within the handler is called branching . Executing the same block of lines repeatedly is called looping . Branching and looping are the stuff of a computer program's "thought"; they are why a computer presents the illusion of being "intelligent." A program may not be truly "intelligent," but it can be responsive because it can base its choice of actions on present conditions, and it can be methodical because repetitive operations can be concisely expressed. It is these attributes, together with its speed and accuracy of calculation, that make a computer useful. In this section, we outline REALbasic's flow-control statements, its commands for branching and looping.
In what follows, when I speak of a condition , I mean a boolean expression. When I speak of testing a condition, I mean that the boolean expression is evaluated. This may sound rather forbidding, but it is actually quite simple and intuitive.
Basically, a boolean is a value that is either true or false, and a condition poses a question that REALbasic can answer by evaluating it as true or false. For example, in this line of code:
if x = 3 then
the phrase x = 3 is not an assignment; it's a boolean expression. This boolean expression is being used as a condition, and we're asking REALbasic to test the condition by evaluating the boolean expression. In this instance, REALbasic is to examine the value of x and see if it actually is 3. If so, the condition is true; if not, the condition is false. Your intuitions about fundamental logic and about how to use concepts such as "if" will work perfectly well here. (The formal explanation of booleans appears in Chapter 5.)
The great power of using conditions for flow control lies in the fact that they are tested (evaluated) right there and then: whether the condition is
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Arrays
An array is a way of associating multiple values of the same datatype with a single name. A particular value to be accessed is specified by an integer in parentheses following the name; this integer is called the index . For example, if we have an array of strings called myStrings, then myStrings(1) would be a string value, myStrings(2) would be another string value, myStrings(3) would be yet another string value, and so forth.
There are two chief advantages to being able to talk this way. One is that in computer programming it is very often the case that we can most easily specify arithmetically which of several values we want. Partly this is just a matter of convenience. If myStrings is an array of 100 strings, it is a lot easier to specify the desired string by one name and an index number than to have to maintain 100 names. But also, a notion such as "the next string" is expressible by a simple arithmetic process—incrementing the index—and thus it becomes very easy to perform such a task as visiting every string. So, for example, to set each of our 100 strings to "hello", one can say:
for i = 1 to 100
    myStrings(i) = "hello"
next
Besides "the next one," there are many other relationships among entities that can be most easily expressed in arithmetic terms. Suppose, for example, we are playing a game on a four-by-four grid; we might designate the 16 squares numerically, as follows:
1
2
3
4
5
6
7
8
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Recursion
One further looping construct demands discussion, namely the ability of a subroutine to call itself; this is known as recursion . Only a subroutine in a method handler can recurse, so arranging your code for recursion can be a bit tricky. For example, if you discover, in the course of writing a button's Action event handler, that you want a certain portion of the code to recurse, you will have to spin that code off into a method handler; you can't recurse within the Action event handler because it isn't a method handler and cannot call itself.
Recursion has an undeserved reputation as something frightening and beyond the scope of beginners, but computer languages in which recursion is basically the only way to loop are taught successfully to novices and children every day. And there are situations where recursion is the obvious way to consider the problem and to express its solution in code.
Suppose, for example, that we have a sorted array of strings, sortedArray, and that we wish to know whether it contains a given string, whatStr. We specify that a function findSorted should accept whatStr as a parameter and return an integer that is the index of the matching string in sortedArray, or 0 if no match is found. (We presume, for simplicity, that sortedArray is available without having to be passed as a parameter; for example, it could be a property.) Clearly we could just examine every item of sortedArray in numerical order, until either we find a match or we deduce that whatStr is absent:
Function findSorted(whatStr as string) As integer
    dim i, u as integer
    u = ubound(sortedArray)
    for i = 1 to u
        if sortedArray(i) = whatStr then
            return i
        elseIf sortedArray(i) > whatStr then
            return 0
        end
    next
    return 0
End Function
The trouble is that this is incredibly wasteful. If the array consists of 10,000 entries, we will have, in the worst case, to loop 10,000 times, performing 20,000 comparisons, before getting an answer.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Comments
A comment is a part of a line that is ignored by REALbasic. A comment is introduced by a comment delimiter; the delimiter and everything after it in the line will be ignored. You have a choice of three comment delimiters:
  • The double slash, //
  • The single apostrophe, '
  • The keyword Rem (short for "remark")
I always use the double slash, as being easiest to see.
If a line consists of only a comment, the comment is ignored and the line consists of nothing: it is an empty line. As was pointed out at the beginning of this chapter, "nothing" is a main verb, meaning that an empty line, and therefore a line consisting of only a comment, is permitted anywhere.
It has become de rigueur in books about programming to lecture the reader on the importance of documenting one's code; so please pretend that the lecture appeared at this point (and consult some other book if you actually want to read the lecture). Unfortunately, effective documentation by way of comments is not at all easy in REALbasic, for three reasons:
  • REALbasic has no syntax for commenting out a block of lines.
  • REALbasic's Code Editor does not provide automatic wrapping of long lines.
  • REALbasic does not permit writing a comment outside a handler's executable code.
The trouble is particularly acute when, as frequently happens, what one wishes to document is not a line of code at all, or even a handler, but rather a noncode entity, such as a property, a control, or a class. One workaround is to create a method handler or handlers consisting entirely of documentation, but this still fails to associate the documentation with the entity it documents. No matter where you put it, documentation is difficult to modify and maintain because of the lack of block comments and line wrapping. What's really needed is that every entity in the IDE should have a "comment window" that pops up on demand and works like a little word processor. Until then, you may find it easiest, as I do, to document your projects using a different application altogether.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Objects, Classes, and Instances
Consider programming as a way of thinking, and code as a way of speaking—a language. The programmer thinks about what the program is supposed to do, and then expresses this in code. An object is a programming construct which assists the programmer both in thinking and in speaking about the program, both in organizing and in coding. The program works as if it consisted of autonomous bundles of functionality—the objects. These objects are somewhat like the bundles of reality, the "things," the "objects," in terms of which we perceive and describe the natural world. Thus, the use of objects in programming makes the programmer's thought and speech about the program more natural, which in turn makes programming easier.
What are the objects of which a program is constructed? In general, that's up to the programmer, who, rather like some divinity creating a small universe, dictates both what objects should populate that universe ("Let there be light; let there be the sun; let there be the earth") and what those objects should do and how they should interact ("Let the sun make light to shine upon the earth"). Such power may seem daunting, almost paralyzing, rather than helpful. Where to begin? If there were an easy answer, there wouldn't be approximately six gazillion books about designing object-oriented programs.
REALbasic both enforces object-oriented programming and helps you with object-oriented design. Before you write a line of code, the construction of your program's universe has already been started for you. The program you are contemplating is to be an application; REALbasic is an application framework, and has stocked your program beforehand with objects that mirror the physical elements of an application's interface: windows, buttons, text fields, menu items, and so forth. Such physical elements of the interface are the objects of the "natural world" the user perceives when working with your application, and so they are the very objects in terms of which it is most natural to think and speak about the operation of your program ("This button should react to being pressed by opening that window").
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Messages and Dot Notation
As a programming construct, objects divide a program into pieces. The glue that unites those pieces to form a single working program is the ability of the objects to send one another commands and ask one another questions. The objects are autonomous, but they can communicate; this communication takes place by means of messages. In REALbasic code, the sending of a message to an object is expressed by dot notation.
Suppose, for example, that we have an object called MyWindow and we wish to tell it to turn blue. We could do this by sending it a TurnBlue message—assuming, of course, that the MyWindow object can accept a TurnBlue message. If it can, then we might say:
myWindow.turnBlue
This shows the basic dot notation syntax whereby messages are sent: the name of the object is followed by a dot, which is followed by the name of the message.
But how does this syntax fit into the larger syntax of the REALbasic language? The answer is that every message is one of two types, both of which are already familiar to us from Chapter 2: it operates, depending on the particular message, either as a subroutine call or as a variable name. As a matter of nomenclature, it happens that the subroutines that can be called by sending a message to an object are called methods, and the variable-like things whose values can be accessed by sending a message to an object are called properties. But syntactically and conceptually, they present nothing new. Since we already know how to use subroutine calls and variable names in code, we already know how to use messages as well.
To illustrate, suppose a particular message designates a method. That means the message operates as a subroutine call. As we know, subroutines can be either procedures or functions, so let's suppose this method, TurnBlue, is a procedure. Then, if that procedure takes no parameters, we might say:
myWindow.turnBlue
If the procedure takes one parameter (perhaps an integer telling how blue the window should turn), we might say:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Object Design Philosophy
Methods and properties correspond to the two primary purposes of objects as programming constructs: encapsulation of functionality and maintenance of state. These two purposes underlie the design of object-oriented code, and an understanding of them will help you to make sense of REALbasic's built-in objects, to appreciate REALbasic's application architecture, to organize your code intelligently, and to know when to create your own objects.
The idea behind encapsulation of functionality is that each object should be the repository of knowledge about how to do all the things appropriate to itself.
Consider, for example, a shoot-'em-up arcade game, where every time the user hits a target, the target explodes, and the score, displayed in a box, increases. Now, we could write such a program without using object orientation at all; it's all just pixels on a screen, after all, and code that controls pixels has the same effect no matter how it's organized. But if we do use object orientation, the very language in which we describe the program, where the nouns are "target" and "score" and the verbs are "explodes" and "increases," suggests that the target and the box containing the score are two different objects, and that it is the target that should contain the code for exploding, and the scorebox that should contain the code for increasing. The target "knows" how to explode; the scorebox "knows" how to increase. In other words, the target object has an Explode method, and the scorebox object has an Increase method.
Messages can be sent to the appropriate objects to instigate the appropriate actions. Instead of exploding the target from elsewhere, we send the target the Explode message, as if to say: explode yourself! Instead of increasing the score from elsewhere, we send the scorebox the Increase message, as if to say: increase yourself! (In fact, our use of the conjunction "and" in describing the program's behavior suggests that it should probably be the target which, as it explodes, tells the scorebox to increase.)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Classes and Instances
An object is an abstraction, a way of thinking and speaking. We come now to the details of how objects are actually implemented in the REALbasic programming environment. They appear in two forms: as classes and as instances. We begin with an explanation of what a class is.
Consider the notion that every object is of some type. The notion of types of object accords intuitively with our ideas of objects in the real world; these two pencils are two different objects, yet they are both pencils. Such a notion implies immediately that our program may have more than one object of the same type; for if this were not possible, and every object were the only one of its kind, the notion of types of object would be superfluous.
The possibility of our program containing more than one object of the same type has both a ready intuitive appeal and an obvious practical value. Returning to our arcade game example, imagine that the user is to be confronted with numerous targets marching across the screen. They look alike, and they behave alike (they explode when hit). It makes perfect sense that we should be able to say and think that each of these targets is a different object (only the one that is hit will explode), yet they are all targets (any one that is hit will explode in the same manner). The same is true of the scorebox; there might be two different scores (how many large targets the user has hit, and how many small targets), each of which is increased individually, and each of which is displayed in a separate box. It makes perfect sense that we should be able to maintain two different scores in two different objects, yet we should be able to say and think that both objects are scoreboxes (each contains a score that it knows how to display and increase).
Figure 3-2 illustrates this notion. The round things, which are marching across the window at the left, are targets. They are different objects; yet they all look identical, because they are all of the same type—each is a target.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Anatomy of a Class
Back in Chapter 1, we learned our way around a Code Editor, and spoke loosely of a Code Editor as belonging to an object. Now we can be more rigorous. As we have just seen, what's edited in the IDE are classes. Thus, a Code Editor provides a view of what constitutes a class. Indeed, it is the best such view, since the other two views, the Properties Window and the Window Editor, show only properties. Not every detail of every class appears in a Code Editor (as I'll explain in a moment), but only in a Code Editor does the general anatomy of a class stand fully revealed.
In order to study the Code Editor of a class, we might wish to make a class. To do so, you choose File New Class, unless the class is to be a window class, in which case you choose File New Window. However, there is no need to do this right now; issues of class creation are the subject of Chapter 4, and it just so happens that even an empty project provides us with one excellent example of a ready-made class—the Window1 window class. So you might wish to open the Window1 Code Editor at this point, to help you follow the discussion.
A Code Editor reveals that a class consists of two sorts of things: handlers and properties. Handlers are containers for subroutines, as explained in Chapter 2. Properties, as explained in the previous section, are variable-like entities belonging to an object, which can be accessed through messages.
You may perhaps have expected, from the previous section, that a class would consist of methods and properties, corresponding to the two purposes of a class, encapsulation of functionality and maintenance of state. This is essentially right, but in REALbasic terminology, there are handlers that are not methods. The reason is that REALbasic organizes its object model to fit into its application framework in a particularly clear, well-defined way. Under this organization, methods are one kind of handler—the kind that can be called by the programmer, in code, by sending a message to an object. Other handlers in a Code Editor get called in a different way, namely, by REALbasic itself, as part of the application framework; I'll say more about this matter in a moment.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
An Instance Is Born
Instances are literally the only things that allow an application to act. Without instances, there will be nothing to send messages to, no methods or event handlers will ever be called, and none of our code will ever run. Remember the Golden Rule, from earlier in this chapter? The objects in the built application's running code are all instances. But the only thing that can be edited in the IDE are classes. So, in the running application, where do instances come from?
Since every instance is an instance of some class, the question amounts to this: how to make an instance of a given class. Another way of putting it is to use the technical verb: we wish to know how to instantiate a given class.
This question will now at last be answered. There are five different cases.
As your application starts up, the Application class (or a subclass of it, if you've created one) is instantiated once, automatically. This single instance persists throughout the lifetime of the application. You cannot instantiate the Application class (or its subclass) in code.
Because an instance of it is absolutely guaranteed to exist uniquely and at all times, the Application class is an appropriate repository for methods and properties that are to be available always from anywhere (globally). Global methods and properties are taken up in Chapter 4. Other features of the Application class are discussed in Chapter 7.
Every application has either one default window class or none. To determine which is the default window class, choose Edit Project Settings and, in the resulting dialog, use the Default Window popup; you can specify any existing window class, or "<none>".
If there is a default window class, an instance of it is generated automatically as the application starts up, just after the Application class is instantiated. This also instantiates the controls within the window, as we shall see. There is nothing special about the default window instance; it's just a convenience so your application has something to get started with, if you like. Nor does the default window class behave specially in any other way. Your code can generate further instances of it, and any instance of it can be destroyed, just as with any window class, by closing the window.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Referring to Instances
Once your application is running and some instances have been generated, much of the action will be precipitated by your code calling methods, and getting and setting properties—in other words, by sending messages to instances.
Many of REALbasic's built-in methods, as was pointed out earlier, are global, but many of them belong to some particular class, and the only way you can call these is by sending a message to an instance of that class. The same is true for methods that you write: you can write global methods (as will be explained in Chapter 4), but for the most part, in line with the considerations presented in Section 3.2 earlier in this chapter, you'll write them as method handlers in some class, and the only way you can call such a method is by sending a message to an instance of that class.
Exactly the same thing is true for properties. Many of REALbasic's built-in classes have properties, and you will often need to retrieve the value of such properties, as a way of obtaining information; for example, getting a window's Top and Left properties tells you where it is on the screen. You'll also frequently want to change the value of such properties; for example, setting a window's Top and Left properties is how you move the window. And of course you'll frequently have properties you've created yourself, and though you can make global properties, more often you'll declare the property in some particular class, and then you'll want to get or set the property's value, in code, and the way you get and set a class's property in code is by sending a message to an instance of that class.
Now, we already know the syntax by which your code will send a message to an instance—dot notation. As explained earlier in this chapter, what appears after the dot will be the name of a property or method, and the syntax of the dot notation expression as a whole is the same as that of a variable name or a subroutine call.
But what about what comes before the dot? This is where you tell REALbasic what instance to send the message to. You do this by providing a
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Truth About Controls
The term control is used in two ways in REALbasic. In general, a control is an instance that is contained in a window. The window automatically generates the instance, when the window itself is instantiated. You can make a control from any programmer-defined class (except a window class), by dragging the class's listing from the Project Window into a Window Editor.
There is also a built-in Control class; an instance of a subclass of the Control class can exist only as a control (that is, it must be contained in a window). REALbasic supplies many built-in Control subclasses; all of these are represented by icons in the Tools Window. A few icons in the Tools Window also represent built-in classes that are not Control subclasses. You can make a control from any class represented in the Tools Window, by dragging its icon into a Window Editor.
When you make a control by dragging into a Window Editor, what are you really doing? Let's suppose that what you drag is the PushButton icon from the Tools Window. This icon represents a class—the built-in PushButton class. In dragging it into a Window Editor, you are not making a new class, because the PushButton class already exists; but you cannot be generating an instance, either, because what you edit in the IDE are classes. What you're actually doing is editing the window class, telling it to contain an instance of the PushButton class. Let's suppose this is the Window1 Window Editor. You're saying to the Window1 window class: "I want there to be a control that is an instance of the PushButton class. This instance is going to be your responsibility, Window1! You contain it. So, part of your job is to instantiate the PushButton class whenever you yourself are instantiated."
This makes perfect sense, because it captures our intuitive notion of window types. Let's say you're writing an email application, and one of your window types is for composing a new email message, and has a Send button in the upper right. You want the user to be able to work on several new messages at once. Therefore, more than one of these email composition windows may have to be open; in object terms, there will have to be more than one instance of this window class. So each of those windows should have a Send button in the upper right, because they are the same type of window.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Control Clones and Control Arrays
There is usually no need for you to instantiate any controls in code, because you have already effectively instantiated beforehand all the controls you're going to need, by dragging them into a Window Editor. The window will instantiate them for you, when it itself is instantiated. That's what it means for an instance to be a control, and what it means for it to be contained in a window.
Nonetheless, you can instantiate a control in code, provided that an instance of that control exists in that window already (ultimately because you dragged it into a Window Editor). In other words, your code, although it cannot create an instance of a control ex nihilo, can clone an existing control. The values of properties can differ from clone to clone (for example, different clones of one button can have different positions in the window), but their event handlers in the window's Code Editor are shared.
You don't have to wait to do your cloning until the application runs; you can clone a control manually, in the IDE. We'll see in a moment why you might want to do this. But first, let's pause to discuss the matter of dynamic creation and destruction of controls.
Some newcomers to REALbasic are disappointed at its inability to create controls dynamically that are not clones. But this limitation is not as serious as it may appear, because no rule says that the existing control, the one that is to be cloned, must be visible. In other words, you can't create a control ex nihilo while the application is running, but you can certainly make it seem as if you did. As far as the user is concerned, a button can be made to appear in a window where none was previously, and that's all that matters. The truth is that this button existed already, but it was invisible, or was located outside the boundaries of the window. In fact, a common technique is to avoid cloning controls in code altogether, through the use of invisible controls. For example, if you know that you will need up to 10 buttons, you can create 10 buttons in the IDE and make them invisible. (If they will all have the same functionality, they can be clones of a single button, or instances of a single button subclass.) When the application runs, if it needs to present one of these buttons to the user, it just makes it visible.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Being Careful with Instance References
The value of a variable or property has a datatype, and this datatype is either a scalar type or an object type. Scalar types are strings, numbers (integers, singles, doubles), colors, and booleans, all taken up formally in Chapter 5. Object types are classes, which is what this chapter is about. When a variable or property has an object datatype, the name of the datatype is the name of a class, and the variable or property can be used as a reference to an instance of that class.
So far, this chapter has explained how to generate an instance, and how to get a reference to that instance. Now it's time to talk about how to work with references to instances.
References to instances are tricky. Paradoxically, this is for the same reason they are so easy. REALbasic tries to shield you from the truth, which is that references to instances are pointers—the value of a reference to an instance is not the data (the instance), but an address (a numeric value stating where in memory the actual instance lives). The word "pointer" doesn't appear in this connection anywhere in the REALbasic documentation. The REALbasic language doesn't make you explicitly dereference a pointer in order to gain access to the properties of an instance; instead, such dereferencing is handled for you implicitly. In short, REALbasic tries to create the illusion that objects are just like scalars.
The purpose of this section is to shatter that illusion and trample its fragments in the dust. My experience is that beginners get into much less trouble when they understand what's really going on. If you remember that references to instances are pointers, and grasp the implications of that one simple fact, you'll manipulate such references successfully. The point is so important that it deserves a paragraph to itself, so here it is:
A reference to an instance is merely a pointer. The instance itself lives elsewhere and has an independent existence.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Destruction of Instances
We know how instances are born; but how do they die? The short answer is that, in general, you're not supposed to worry about this. REALbasic does its best to shield you from problems of instance destruction. Those problems are intimately related to memory management; and one of REALbasic's great strengths is that it manages memory for you.
The core of REALbasic's memory management system is a principle called garbage collection. This states that REALbasic will see to it that an instance will go out of existence all by itself when appropriate, and the memory that it used to occupy will be cleared. In particular, REALbasic uses a style of garbage collection called reference counting; this states that an instance is destroyed as soon as there is no way at all for code to refer it. Internally, the implementation is that every instance is accompanied by a property, its reference count, invisible to the programmer, which is incremented every time a reference is assigned to point to that instance, and decremented every time such a reference ceases to point to the instance or ceases to exist. You can manually cause a reference to cease to point to an instance, by setting its value to nil; otherwise, a variable goes out of existence automatically when its subroutine terminates execution, and a property goes out of existence automatically when the instance that owns it goes out of existence. An instance is destroyed when its reference count drops to zero. (Actually, the programmer can get access to an instance's reference count, through the built-in Runtime object; this is discussed in Chapter 8.)
For example, if a subroutine instantiates a FolderItem, assigning