Contents. Chapter 1: Getting Started

Size: px
Start display at page:

Download "Contents. Chapter 1: Getting Started"

Transcription

1 Beginners Guide to Dolphin Smalltalk Beginner's Guide to Dolphin Smalltalk Welcome to Dolphin Smalltalk for Microsoft Windows 95 and NT. By now, you have probably installed Dolphin onto your computer and are wondering where to go from here. This guide is the place to start. Contents I know you're probably itching to get going, but I'd just like to take time out to tell you about the structure of this guide and the intended audience for the various parts. Chapter 1: Getting Started This chapter will get you started with Dolphin and teach you how to interact (safely) with the system. If you have used Smalltalk before, much of this will be familiar to you so you may just need to skim through this section quickly. The following chapters are a general introduction to the Smalltalk language and, in spirit, are as applicable to any other implementation of Smalltalk as they are to Dolphin. In practice, we'll use a sample application called Playground to illustrate the various topics and currently this is only available in Dolphin Smalltalk. If you are already familiar with the basic Smalltalk language, you may decide to skip over these chapters. Chapter 2: Objects and Messages Chapter 3: Playing with Objects in the Playground Chapter 4: Control Flow Chapter 5: Classes and Methods Chapter 6: Programming in Smalltalk From this point on there are a number of tutorial sessions available to teach you how to use the Model-View-Presenter framework which lies at the heart of building applications in Dolphin. The following chapters are specific to Dolphin Smalltalk. Tutorial 1: Experiments with Simple Windows Tutorial 2: A Scribble Pad Component file:///c /OADocs/1.htm (1 of 2) [6/2/2000 8:39:12 AM]

2 Beginners Guide to Dolphin Smalltalk Tutorial 3: Etch-A-Sketch Tutorial 4: Creating a Personal Money Application file:///c /OADocs/1.htm (2 of 2) [6/2/2000 8:39:12 AM]

3 Getting Started Getting Started This chapter gets you started with Dolphin Smalltalk. The installation program will have created a program folder containing a Dolphin icon. Double-click this to start the Dolphin development system. Obtaining Support There may be times when you run across a problem with Dolphin that you can't solve yourself. If so, you can obtain technical support from Object Arts Ltd. by Internet or by connecting to the special Dolphin newsgroup forum. For more details, please visit the Object Arts Support web page at: First Use When you start Dolphin for the first time, you will be presented with two windows: a System Folder window and a Workspace window. The workspace contains a welcome message and some interesting experiments that you can try immediately to get an insight into the interactive nature of the Smalltalk development environment. These experiments consist of executing small pieces of Smalltalk code and displaying the results. Note that the green pieces of text enclosed in quotes are simply comments and not part of the examples themselves. Most of the examples fit on a single line. To execute one (say the first, 3+4) simply place the text cursor anywhere on that line and type Ctrl+D. You'll see the result printed and highlighted at the end of the line. You can then delete the result simply by pressing the Del key and the highlighted text will disappear. file:///c /OADocs/2.htm (1 of 4) [6/2/2000 8:39:21 AM]

4 Getting Started In some cases, the comment above the example will suggest that you just execute the code without actually displaying a result. You do this by typing Ctrl+E (for Evaluate It) rather than Ctrl+D (for Display It). These commands can also be chosen from the Workspace menu. Simply choose Workspace/Display It or Workspace/Evaluate It as required. For those examples that span several lines you must select and highlight all of the lines before typing Ctrl+D or Ctrl+E. If you are new to Smalltalk, then I don't really expect you to understand how these examples work yet. They are simply there for a bit of amusement and to get you used to using a workspace window. You can close the workspace at anytime and continue with the remainder of this chapter. Opening a new Workspace If you have not already done so, close the example workspace window that you've been using up to now. You should then be left just with the System Folder open. As we've seen, a workspace is a general text window where snippets of Smalltalk code can be edited and executed (in Smalltalk parlance, evaluated). It is one of a number of development tools that Dolphin provides. For the next few chapters we will be using workspaces, almost exclusively, to interact with the system and perform our experiments. At the start of each chapter you'll be asked to open a new workspace in which the work for that chapter will be performed. You can do this by choosing the File/New menu command from any other workspace or Dolphin development tool window. You may also use the New Workspace toolbar button or the Ctrl+N shortcut if you prefer. At the end of each chapter you should probably tidy up by closing the workspace (and any other example windows) that you have been using. This will free up any memory space and leave the system ready for continuing with the subsequent chapters. Exiting Dolphin You can leave Dolphin at any time by choosing File/Exit Dolphin in any of the development tools. Alternatively, you can also ask to quit by closing the System Folder window. As you do so, you will be prompted and asked if you wish to save the image. Under normal circumstances you will opt to do so, since this will save the state of your environment such that it will be fully restored next time you start Dolphin up. Try exiting and re-starting Dolphin now, saving the image in the process. The Image When Dolphin is loaded and running there are many objects in memory that make up the essence of the entire system. I will talk more about what objects are in the next chapter on Objects and Messages. However, for the moment, it is important to know that when you choose to save the Dolphin image you are requesting that all these objects be saved to disk in, what is known as, an image file. This allows the system to be re-started in an identical state to that when the image was saved. When should I save my Image? The image contains not only those objects that you may create yourself but also very many objects that are concerned with the Dolphin development system itself. This is a really flexible system since virtually everything is exposed to you and you can make changes that affect not only the program you may be building but also any of the development tools themselves. This can allow you to tailor the system in ways that are not possible with traditional development environments. However, this flexibility also brings with it certain dangers. You may, by accident, make a change that corrupts your image such that the development tools no longer work. For this reason, it is always important that you have a good saved image to go back to. I'd recommend that you save your image, not only when you exit Dolphin, but also quite often during use. I suggest you do this at least every hour and once at the end of each chapter in this guide. Do take care, though, not to save down an image that you might have corrupted in any way. Let's try a simple example to prove the point. Open up a new workspace window and arrange it appropriately on the screen. Now file:///c /OADocs/2.htm (2 of 4) [6/2/2000 8:39:21 AM]

5 Getting Started save the image using File/Save Image or the Save Image toolbar button (the one with the camera). This will save your current state to an image file on disk. Now let's do some irreparable damage and recover from it. Enter the following line of code into your workspace and evaluate it with Ctrl+E: Processor := nil. You'll see that the development system will crash. This is not surprising really when you consider that you have just instructed the main processing element to disappear. However, now restart Dolphin and you should get back to the same state you were in when you previously saved the image. Backups Ideally, you should also take backups of your Dolphin image files. If you do so, you must always save the following three files together: Image file (Dolphin.img) Changes file (Dolphin.chg) Sources file (Dolphin.sml) You'll find these files in the directory where you chose to install Dolphin itself. If you need to restore a backup (perhaps because you accidentally do save down a corrupt image at some point) then you must make sure that you restore all three files together. These files are inextricably linked and should not be separated. I tend to take a backup of my Dolphin image files daily. The System Folder The System Folder window has been lurking in the background during all of this and we haven't paid much attention to it. In many ways it is launching point for all the tools in the development system. Let us see how this works. Double-click on the icon for the System Transcript. The System Transcript The System Transcript is, in some respects, similar to a standard workspace window. file:///c /OADocs/2.htm (3 of 4) [6/2/2000 8:39:21 AM]

6 Getting Started You can use it to evaluate pieces of Smalltalk code just like you been doing in workspaces, however, this is not its main purpose. It is used as an easily visible location where information can be logged and brought to your attention. The development system may choose to write things to the Transcript or you may do so yourself. Try this by evaluating it in a workspace (with Ctrl+E): Transcript cr; show: 'Hello world'; cr. You should see that this welcome text has now been logged to the Transcript window. What have you learned? The aim of this chapter was to get you started with Dolphin. By now, you should be familiar with: Starting Dolphin Workspaces Exiting Dolphin Saving the Image Taking Backups The System Folder The Transcript Click here to move on to the next chapter or here to go back to the previous chapter. file:///c /OADocs/2.htm (4 of 4) [6/2/2000 8:39:21 AM]

7 Objects and Messages Objects and Messages Smalltalk is what is known as an Object Oriented Programming Language. When you start your Dolphin image you bring into your computer's memory a sea of interconnecting and communicating objects. This chapter introduces the ideas behind what objects actually are and how you can use messages to communicate with them. Please open a new workspace window using File/New so that you can try out the examples presented below. What is an Object? At the simplest level, an object is just an area of your computer's memory that contains some data bytes describing the object's state. For example, an object representing the text string, 'hello', would contain (amongst other things) the bytes: Here each byte, of course, represents one character in the string. However, every object also contains additional information that allows it to "know" what kind of object it is. How this knowledge is encoded as part of the object is not relevant at this stage, but it is very important since it allows the object to determine how it should behave. For example, if we have two objects that are numbers it seems quite reasonable that we should be able to subtract one from the other. If, however, we had two text strings we would not expect to be able to perform a similar subtraction operation. The fact that the number objects "know" that they are numbers allows them to determine that subtraction is a relevant operation and also how that subtraction should be performed. In Dolphin, there are objects that represent (amongst other things): Text strings Numbers Dictionaries Text editors Windows Programs In Smalltalk: Everything is an object. All objects know what kind, or class, of object they are. Class is a very important word in Smalltalk parlance. The class of an object allows it to determine how it should behave. Tip: the fact that everything is an object in Smalltalk is highly significant. It makes Smalltalk a very pure object oriented programming language, much more so than other languages such as C++ or Java. This purity imparts a uniformity to the system that means that the language can be simple to learn and yet very powerful. When you are programming in Smalltalk, some objects can be represented directly in the language. These are called literals. Take a look at the following examples of literal objects: 'Hello world' - a text string $H - the character H an integer number a floating point number #(1 2 3) - an array of three integers file:///c /OADocs/3.htm (1 of 11) [6/2/2000 8:39:45 AM]

8 Objects and Messages #show - a special object called a Symbol Objects communicate with Messages In Smalltalk, objects send messages to one another to cause things to happen. How an object responds to a particular message is determined by the class of object that it is and it is important to realize that not all objects respond successfully to all messages. The set of messages that an object can understand, and its response to these messages, determines the behavior of the object within the Smalltalk system. All objects know what set of messages they can understand. This set is governed by the class of the object. The following are typical of messages that might be sent: + - new show exit includes: assortedcollection You can use the Smalltalk language to create objects and send messages to them. Create a new workspace window (File/New) and try the following examples. You should display the result of evaluating each line individually. Tip: Remember that you don't have to select the entire line to do this, just place the insert cursor somewhere on the line and type Ctrl+D (Workspace/Display it) to cause it to be evaluated and the answer displayed. 3+4 'Hello world' reverse 5 factorial Simple Messages A Simple Message is one that requires no additional information or parameters apart from the message itself. Such messages must begin with a lower case letter and the remainder of the message keyword can consist of any letters or digits or the underscore (_) character. Try displaying the results of the following examples: 5 squared. Here the message squared is sent to the integer object 5. All messages return an answer of some description and, in this case, it will be 25. One great thing about Smalltalk is its ability to handle very large numbers of effectively unlimited precision. Try this: 200 factorial Here are some more message sends: 'mary had a little lamb' asuppercase The message asuppercase, when sent to a string object, causes a new string to be created with the contents of the original converted to upper case letters. This new string is then answered as the result of the message. #( ) size file:///c /OADocs/3.htm (2 of 11) [6/2/2000 8:39:45 AM]

9 Objects and Messages The message size, when sent to this array object containing five integers, answers the number of elements in the array, in this case, 5. The object to which a message is sent is called the receiver. The message itself is sometimes called a message selector (because it selects which operation will be performed) and the result is generally referred to as the answer. Messages that are not understood We mentioned before that an object will only respond to a certain set of messages depending on what class of object it is. For example, objects that are kinds of number will hopefully handle arithmetic messages successfully. We would not, however, really expect text string objects to behave in the same way. Let's deliberately send a dubious message to a string: 'Hi Andy' squared Notice that this causes a walkback window to pop-up. Dolphin uses these windows to indicate when some sort of error has occurred. The window caption indicates the basic problem, in this case, String does not understand #squared. At this stage, you could choose to enter the system debugger (by pressing the Debug button) to further diagnose the problem. However, understanding the debugger is perhaps beyond us at this point so, for the time being, get used to clicking on Terminate when you see a walkback pop up. Sending Messages on top of Messages When you send a message to a receiver, you always receive another object back as the answer. It seems perfectly reasonable that you should be able to send further messages to this answer. Try: 20 factorial displaystring Here, the message displaystring, is sent to the result of 20 factorial. Look carefully, and you'll see that what is displayed is surrounded by single quote marks, thus indicating that the integer result has been converted to a text string representation. Perhaps we might additionally want to know how many characters are in the display string for 20 factorial: 20 factorial displaystring size So you can see that you can use sequences of messages to create more complex expressions. Binary Messages Sometimes, a message needs additional information to perform its work. Certain messages, called Binary Messages, require two objects; the receiver and one parameter. Try: * 5 5 squared ** 3 The latter ** message selector represents exponentiation, so this expression computes 4 to the power 3. Here, the integer object 4 is the receiver and 3 is the single parameter required by the ** message. As you can see, binary messages are often used to perform arithmetic in Smalltalk. The message selectors consist of file:///c /OADocs/3.htm (3 of 11) [6/2/2000 8:39:45 AM]

10 Objects and Messages one or more special characters that are not letters or digits. They can be used for other operations too: 'skin', 'diver' The, message is used for concatenation. In this case it is used to append the string 'diver' to the receiving object, the string 'skin'. The operation answers a new string that contains the concatenation of the two source strings. In fact, this message can be used to concatenate many similar collections of objects: #(1 2 3), #(4 5 6) Sometimes, messages are used simply to "construct" a new object. We'll hear more about these constructor or class messages later but here is an interesting example using the binary 150) class message, when sent to an integer, is used to create a two-dimensional point object. The class message simply asks the resultant object to answer what class it is (we'll learn more about classes later). The interesting thing here is that the sequence 50@150 appears, in the Smalltalk language, to represent a two-dimensional point, but, it's important to understand that symbol is not part of the language per se. Rather, it is simply a message that performs a particular operation (in this case the creation of a point object) just like any other binary message. Just for fun, try some more operations on points. 150) + 35) 480) * 3 Keyword Messages We have seen above that binary messages take a single parameter. Binary messages are special characters such as: + * - /etc. It is also possible to supply parameters to the more alphabetical style of message selectors. #( ) at: 2. #( #( 1 2 3) ) at: 3 As shown above, the at: message can be used to access an object at a particular index within an array, or other indexable collection. In the second example, you see that you can have quite complex arrays which even include other arrays as their elements. This makes sense since an array can easily hold any type of object. Here are some more examples of keyword messages that take a single parameter: #( #( 1 2 3) ) includes: 30 squared 'Hello World' occurrencesof: $o 1 to: 10 The latter is another example of a constructor message similar In this case to: sent to an integer will answer a special sort of collection known as an Interval. Intervals can be used where any other collection can be used and this one represents the range of integer numbers between one and ten. To see this better, ask it to convert itself to an array: (1 to: 10) asarray So far, we have seen how single parameters can be passed to messages ending in a :. Messages can also be created that take any number of parameters: #(1 2 3) at: 2 put: 'Hello'; yourself We'll come back to the use of the semicolon and yourself message in the section on Cascading Messages below. For the time being concentrate on the at: and put:. These are not two separate message sends but one single one that takes file:///c /OADocs/3.htm (4 of 11) [6/2/2000 8:39:45 AM]

11 Objects and Messages two parameters. We refer to the selector for this keyword message as at:put:. As you can see, this at:put: message can be used to store objects into indexable collections such as arrays or strings. Try these: 'Thomas,Henry,Edward' copyfrom: 8 to: 12 'Thomas,Henry,Edward' midstring: 5 from: 8 'Hello World' at: 6 put: $-; yourself 'The brown quick fox' replacefrom: 5 to: 15 with: 'a quick brown' startingat: 3 Can you say what the message selector in the last example is? Yes, it's a single message that takes four parameters and has the selector, replacefrom:to:with:startingat:. Tip: I hope you can see that this way that Smalltalk has, of interspersing parameters within the body of the message selector, can lead to much more readable program code than with most other languages. If you are used to languages such as C++ or Java you may find this odd at first but I'd wager that, pretty soon, you'll come to like it! Comments Comments can be inserted into your Smalltalk code to provide additional information to help the program reader. A comment is simply text that is enclosed within double quotes. "This is a comment" Generally, Smalltalk requires fewer comments than often appear in other languages because the program text is very readable. You should only add comments where they significantly enhance the understandability of the code. Comments can appear anywhere but they must not breakup the fundamental items of the language such as message selectors or numbers. For example: 365 "Days per year" * 24 "Hours per day" is legal, whereas: 36"Days per year"5 * 2"Hours per day"4 is not. The latter will generate an error from the Dolphin Smalltalk compiler. Tip: users of other languages will be used to using double quote marks to denote text strings. It is obviously important that you take special note of this difference with Smalltalk: double quotes delimit comments and single quotes delimit literal text strings. Arithmetic Let's have a look at the messages for performing simple arithmetic on numbers "Addition" "Subtraction" * 24 "Multiplication" 8766 // 24 "Integer division with truncation" 8766 / 24 "Standard division" file:///c /OADocs/3.htm (5 of 11) [6/2/2000 8:39:45 AM]

12 Objects and Messages The interesting thing to note with Smalltalk arithmetic is that it is not necessary to match the types of numbers involved or to predict the type of the result. For example, it is perfectly reasonable to subtract an integer from a floating point number and arrive at an appropriate floating point result. You should also be familiar with the difference between the integer division and standard division messages. The former (//) will always truncate the result to the nearest whole integer below it. The latter (/) will maintain precision in the result by answering a fractional or floating point result as best it can. The fact that Smalltalk arithmetic is capable of switching between different number representations in order to maintain precision wherever possible is a valuable concept. Wherever possible it will try to avoid using a floating point object to hold a value since many floating point calculations are inherently inaccurate in the lower decimal places. Using objects (of class Fraction) to represent fractional values can mean that ultimate precision can be maintained where it would otherwise be lost. For example: 6 / 18 If this irrational result had been coerced to a floating point value ( ) then any subsequent calculations on this value might lose precision. However, the fractional value (1/3) remains entirely accurate. The only problem might be that you don't wish to display a fraction as the end result of your calculation since most people find floating point print outs more acceptable. The answer is simple, just forcibly convert to the appropriate representation when you want to display the result. You can try this with: (6 / 18) asfloat Order of Messages The order in which Smalltalk evaluates more complicated arithmetic expressions is different than you might expect, especially if you're used to other computer languages. For example, try displaying the result of: * 5 You might expect to see a result of 23 but Smalltalk reports 35. This is because we normally think of multiplication and division operators having a higher precedence than addition or subtraction operators. We would expect the higher precedence multiplication to be performed before the lower precedence addition. This is not the case, however. In Smalltalk, all binary messages are taken to have the same precedence and will be evaluated in "first come, first served" order. This is a minor inconvenience but can be remedied by always using appropriate parentheses whenever there might be confusion. See that the following now yields the expected result: 3 + (4 * 5) Smalltalk does enforce some precedence rules, though. They are very straightforward and, in most cases (apart from the above quirk concerning arithmetic precedence) they yield code that is eminently readable. The order of message evaluations in any expression is as follows: Simple Messages (highest precedence) Binary Messages Keyword Messages (lowest precedence) Try the following examples and try to predict the results: 3 squared + 4 squared #( ) at: factorial gcd: 'a string' size "gcd: computes Greatest Common Divisor" 3 squared + 4 squared sqrt file:///c /OADocs/3.htm (6 of 11) [6/2/2000 8:39:45 AM]

13 Objects and Messages (3 squared + 4 squared) sqrt Variables and Assignments So far, we have been evaluating individual Smalltalk expressions and displaying the results. A Smalltalk program of any real value must consist of many such expressions and, for them to be useful, it's going to be important to store the results somewhere. All computer languages use variables in which to place intermediate values so that they can be retrieved at a later time. In Smalltalk, a variable is a named slot or placeholder into which any object can be stored. A variable name must begin with a letter but subsequently, may consist of any letter, number or underscore characters. The following are valid variable names: name address dayofweek outercount2 day_of_week Although the last variable, day_of_week, is a valid name, in Smalltalk it is conventional to compose this without the underscore characters but by capitalizing subsequent words. Thus, dayofweek would be the preferred name. You can store an object into a variable using an assignment. Try the following breakdown of Pythagoras' theorem. If you wish, you can just evaluate (using Ctrl+E) the first few lines and only display the answer (using Ctrl+D) for the last line. a := 6. b := 7. hypotenusesquared := a squared + b squared. "By Pythagoras" hypotenuse := hypotenusesquared sqrt. Perhaps you've noticed something else new here in addition to the use of the assignment (:=) operator. The Smalltalk language uses a full stop or period (.) to separate individual expressions. Now you can evaluate several expressions in one go. Try the above example again but this time select all of the text before asking to display the result. One thing that is different between Smalltalk variables and those used in other languages is that they are un-typed. A Smalltalk variable is just a slot capable of holding any object; you do not have to declare a variable as being able to hold only a particular type. This makes Smalltalk variables very much easier to use and, in the end, more flexible. Tip: the un-typed nature of Smalltalk variables is often cited as an indication that Smalltalk is not a "safe" language. Languages with strongly typed variables, that insist on a variable being declared as able to hold only a particular type of value, are seen as being safer because the compiler can perform more checks and therefore reduce the number of problems that arise at runtime. However, Smalltalk IS eminently type safe. Even if an incorrect class of object is placed in a variable slot, the problem will not go unnoticed during runtime testing. The object will not respond to the same set of messages that will be expected of it and will throw up a Walkback dialog when an unsuitable message is not understood. Dolphin Smalltalk supports three different types of variables, Workspace, Temporary, Instance and Global. file:///c /OADocs/3.htm (7 of 11) [6/2/2000 8:39:45 AM]

14 Objects and Messages Workspace Variables Workspace variables are owned by the workspace in which they are created. They are created automatically when an assignment is made to a variable beginning with a lowercase letter that has not already been declared. The variables in the above example are all workspace variables. The variable slots and the objects that they contain remain in existence until the workspace is closed. For example, try now to display: hypotenuse. This variable, created by the previous sample, is still in existence and continues to contain the result that was calculated. It will remain while the workspace window is still open and will be accessible to any other expressions that are evaluated in the same workspace. It will not, however, be visible from any other workspace that is opened. Temporary Variables It is also possible to use temporary variables that exist only during the evaluation of a series of expressions. These variables must be declared and their names must appear enclosed by vertical bar characters before the first of the series of expressions in which they are used. Temporary variable names must begin with a lowercase letter. You must select all of the following code to evaluate it and display the result as one unit, c d theta c := 8. d := 4. theta := (d / c) arcsin * 360 / (Float pi*2). Once the evaluation is complete all of the temporary variables are automatically destroyed. It is not that common to use a temporary variable when evaluating expressions within a workspace; most often you will want to use workspace variables instead. Temporaries are more often used in methods, a subject that will be dealt with in the later chapter, Classes and Methods. Instance Variables Objects have to hold their state information somewhere, and instance variables are the place. An object can contain one or more variable slots where its internal data is kept. Instance variables are private to the object in question and are not exposed to the outside world. This allows the object to keep its internal representation hidden so its users don't come to rely on it. Since it is not permissible for a user to manipulate another object's instance variables so messages become the only means to communicate with it. This encapsulation is a very important principle behind Object Oriented Programming. I'll show you how to create and use instance variables in the chapter on Classes and Methods. Global Variables Global variables are similar to workspace variables except that they are owned by the system rather than a particular workspace. Once you create a global it remains in existence, holding onto any contents that you may assign to it, until you explicitly remove it. A global variable name must begin with an upper case letter. If you execute the following code, you will be prompted as to whether you wish to create the global, MyName. Click Yes to do so. MyName := 'Arthur J. Rank'. MyName, ' was here'. It is important to cleanup any globals that you may create after you have finished using them. To do this for MyName, file:///c /OADocs/3.htm (8 of 11) [6/2/2000 8:39:45 AM]

15 Objects and Messages evaluate the following (note the # sign immediately preceeding the name): Smalltalk removekey: #MyName. You should find that you don't end up explicitly creating global variables very often. However, there is one sort of global that you will create regularly. Globals are used to hold the class objects that will form the basis of much of your Smalltalk programming. These are also introduced in Classes and Methods. Smalltalk maintains quite a number of global variables of which most are classes. Another, which you'll often find useful, is Transcript. This can be used to reference the System Transcript window in order to send useful text reports to it: 10 timesrepeat: [Transcript show: 'A useful message?'; cr]. Check the Transcript window to see the message logged to it 10 times. Cascading Messages Let's try creating a new window and manipulating it. Evaluate the following lines individually to see the incremental effect: window := ShellView new show. At this point you will have to switch back to the workspace since your new window will be brought to the front. Let's continue: window position: 80@80. window extent: 320@90. window backcolor: Color red. window caption: 'My Red Test Window'. We are sending a sequence of messages to the same receiver. It's quite convenient that Smalltalk offers a shorthand way of doing this, by cascading the messages to a common receiver. The following code performs a similar sequence but must be evaluated in one go since all the lines are effectively part of a single expression. window := ShellView new show. window position: 80@80; extent: 320@90; backcolor: Color blue; caption: 'My Blue Test Window'. Here, each of the cascading messages is separated by a semicolon. Each is sent in turn to the object held in the window variable. The lines are intended by one tab position merely as a matter of Smalltalk style to make the code more readable. Remember to close your red and blue windows now you've finished with them. So what is the result of a series of cascading messages? Well, it's the answer from the last message in sequence. Try this: rect := Rectangle origin: 0@0 extent: 10@10. rect area We've created a Rectangle object with an area of 100 square units. Now let's modify the rectangle to be eight units square and re-compute the area. Once again you'll have to evaluate this as a single expression: rect top: 1; file:///c /OADocs/3.htm (9 of 11) [6/2/2000 8:39:45 AM]

16 Objects and Messages left: 1; bottom: 9; right: 9; area The result displayed is that answered by the last message in sequence, area. Yourself Sometimes it is useful for a series of cascaded messages to answer, not the result of the last message, but the receiver of the messages itself. You can use the message, yourself, to do this. Compare the following two examples: sequence := OrderedCollection new add: 1; add: 4; add: 9; add: 16. Here, the displayed result is 16, which is answered by the final add: message (it is convention that any add: message will always answer its parameter). This is probably not what we want since the actual sequence of numbers has now been lost. More likely, the following is what is expected: sequence := OrderedCollection new add: 1; add: 4; add: 9; add: 16; yourself. The message yourself always answers the receiver that it is sent to. In this case the receiver is the OrderedCollection object and so, since yourself is the last message sent in the cascaded sequence, this is what is returned as the result. Message Selectors are Symbols We mentioned previously that, in Smalltalk, everything is an object. This also goes for message selectors; they are objects too. In fact, they are examples of a certain class of object called Symbols. Symbols are similar to text string objects except that they are prepended with a # sign rather than being enclosed in single quotes. The following are all examples of literal Symbols. #show #at:put: #add: Symbols cannot contain spaces. The important thing about Symbols is that they are unique. This will be explained in more detailed in the chapter on Equality and Identity but the important thing to remember is that message selectors are, in fact, Symbols. For this reason, they are usually written as being prepended by a #. This will be the convention used from this point on in this guide. file:///c /OADocs/3.htm (10 of 11) [6/2/2000 8:39:45 AM]

17 Objects and Messages What have you learned? This chapter has been a long haul simply because of the fact that Smalltalk is nearly all to do with Objects and Messages. For this reason, you can now console yourself with the knowledge that you have covered around 80% of the entire Smalltalk language. So far, you have learned about: Objects Simple messages Binary messages that take one parameter Keyword messages that take one or more parameters Sequences of messages The order or precedence of messages Cascading messages to a common receiver Comments Simple arithmetic Workspace, temporary and global variables Assigning to variables Perhaps most importantly you should also know that: Everything in Smalltalk is an object Every object is of a particular class that governs its behavior As I say, we have now covered probably around 80% of the language of Smalltalk. There are very few other computer languages for which you could do this in a single chapter. The Smalltalk language is quite small because it takes a few simple concepts, such as Objects and Messages, and applies them consistently throughout. This is why you should have found the basics fairly easy to grasp so far. However, there is still a great deal to learn. Although the language itself is small, the Smalltalk system is quite large, and this is what makes it a rich and powerful environment in which to work and play. So, we've got a long way to go but, hopefully, you'll find it's worth it. It's probably best, at this stage, to close the workspace window you've been working with so far. This will clean up any workspace variables you've created. We'll open a new workspace at the start of each subsequent chapter. Click here to move on to the next chapter or here to go back to the previous chapter. file:///c /OADocs/3.htm (11 of 11) [6/2/2000 8:39:45 AM]

18 Playing with Objects in the Playground Playing with Objects in the Playground Okay, let's be honest. The previous chapters have been a little dry and it's about time we had some fun. I'd like to introduce you now to a sample application for Dolphin called Playground, which we can use to consolidate some of the ideas you've learned so far. First of all, you will need to install the Playground package into your Dolphin image. Follow the steps below to do this using the Dolphin Package Browser. Open the Package Browser by choosing the Tools/Package Browser menu command from within any Dolphin window. Within the Package Browser choose Package/Install to bring up an Open Package dialog. You should find the Playground package in the Samples/Playground directory beneath the location where Dolphin is installed. Double-click over Playground.pac to install it into your image. Tip: If you can't locate the package on your local computer then you can download it from the web. Please make sure you save this file in a Samples/Playground subdirectory beneath your Dolphin installation. Once this is complete, close the Package Browser and save the image. A Playground is a window to which you can add visible shape objects and then communicate with them by sending messages from a workspace. It looks like this: You can send messages to perform operations on the shapes, causing them to move, rotate, grow and change colour. As each operation is executed, the Playground window updates as necessary to show the new state of its shapes. You can also send messages to query and display information about the shapes and their current states. A typical dialogue in a workspace might appear as follows: file:///c /OADocs/4.htm (1 of 6) [6/2/2000 8:40:01 AM]

19 Playing with Objects in the Playground Now open another new workspace to use for the examples in this chapter.. Creating a Playground The Playground package introduces several new classes of object into your image. One of these is the Playground class itself, which represents the functionality behind a Playground window. Let's create such a window: playground := Playground new. Here we send a #new message to the Playground class and this results in a Playground window being created. You'll see this appear on your screen. The Smalltalk object that represents this window will also have been assigned to the playground workspace variable. We can use this to communicate with the Playground in subsequent examples. Tip: we don't fully introduce the idea of classes until the later chapter on Classes and Methods. However, it should be apparent from what we have just done, i.e. sending a message to a class, that classes are indeed objects too. If this sounds odd, then don't worry at this stage. Just remember: in Smalltalk, everything is an object. Arrange the Windows on the screen so you can simultaneously see the Playground and your current workspace. file:///c /OADocs/4.htm (2 of 6) [6/2/2000 8:40:01 AM]

20 Playing with Objects in the Playground Adding Shapes to a Playground A number of additional classes, representing a variety of shapes, were also added as part of the Playground package. The ones we're interested in at the moment are Triangle, Square and Circle. Let's add one of each of these types of object to our current Playground: teresa := playground add: Triangle new. simon := playground add: Square new. charlie := playground add: Circle new. Once again, we create an object of a class (Triangle, Square, Circle etc.) by sending #new to the class. As each new shape object is created, we add it to the Playground by passing it as a parameter to an #add: message. We assign the shapes to some friendly variables so that we can "talk" to them later. Tip: you may remember from the previous chapter that it is a convention that an #add: message will always return the object that is added as its answer. So now we have workspace variables identifying: "Teresa the Triangle" "Simon the Square" and "Charlie the Circle" Talking to Teresa, Simon and Charlie Now let's ask our shapes some questions. Evaluate the following expressions in turn and display the results using Display it (Ctrl+D). teresa position. simon position. charlie position. Note that the position of each shape is answered as a two-dimensional point. This marks the location of the center of the shape within the Playground window. Tip: It is an oddity of the way Microsoft Windows works that y coordinates increase toward the bottom of the screen or window. There are number of other messages you can send to the shapes to query information. Try these: teresa sides. simon rotation. charlie color. file:///c /OADocs/4.htm (3 of 6) [6/2/2000 8:40:01 AM]

21 Playing with Objects in the Playground teresa radius. All the shapes respond to a #radius message and answer the radius of their smallest enclosing circle. You'll see in a minute that the radius of a shape is what governs its overall size. Try asking the Playground itself what shapes it contains: playground shapes. Making them Jump Teresa, Simon and Charlie will also respond to a number of messages that ask them to perform operations. Try evaluating the following expressions with Ctrl+E: simon radius: 80. simon rotateby: 10. simon moveup: 30. charlie color: Color magenta. charlie growby: 20. teresa position: 300@100. teresa choosecolor. teresa growby: 15; moveby: 15; color: Color green. Remember that the last example is a cascaded sequence of messages so you'll need to select all the lines to evaluate them simultaneously. Experimenting Nearly all the "fun" of Smalltalk is that you can dynamically interact with the objects that you create. Why not now try some experiments on your own? Ask the Playground objects to perform some operations and then query their states. Perhaps you'll want to add some new shapes. The following messages are available for you to play with. Message Parameter #sides None file:///c /OADocs/4.htm (4 of 6) [6/2/2000 8:40:01 AM]

22 Playing with Objects in the Playground #sides: An integer #radius None #radius: A number #rotation None #rotation: A number #position None #position: A point #color None #color: A color #growby: A number #shrinkby: A number #rotateby: A number #moveby: A point #moveup: An integer #movedown: An integer #moveleft: An integer #moveright: An integer #choosecolor None Remember, if you make a mistake (perhaps by providing an incorrect type of parameter), you'll most likely bring up a walkback. This protects you from doing any real damage. If this happens, simply click Terminate to continue and then try to fix the problem. If you really get into trouble you should be able to clean things up by closing the Playground window and the associated workspace and starting again. What have you learned? This chapter should have firmed up some of the ideas about objects and messages that were introduced in the previous chapter. Now you have learned about: The Playground sample application file:///c /OADocs/4.htm (5 of 6) [6/2/2000 8:40:01 AM]

23 Playing with Objects in the Playground Creating new objects using a #new message Creating a Playground window Adding shapes to a Playground Manipulating and querying Playground shapes Using the Package Browser to install a new Package into your Dolphin image In subsequent chapters we will reuse the Playground application to illustrate some more features of the Smalltalk language. For now, tidy up by closing your existing Playground and workspace. Click here to move on to the next chapter or here to go back to the previous chapter. file:///c /OADocs/4.htm (6 of 6) [6/2/2000 8:40:01 AM]

24 Control Flow Control Flow So far we have seen how to use individual expressions or sequences of expressions to send messages to objects and cause things to happen in our Smalltalk world. However, we are not going to be able to progress much further without the ability to perform tests and make decisions based on the results of these tests. We are also going to want to perform some repetitive tasks (well that's what computers are good at after all) so we'll want to see how Smalltalk handles looping repeatedly around blocks of code. Setting up a Playground for Experimentation We are going to use a Playground window once more to demonstrate the examples in this chapter. You will also need to open a suitable workspace and then create a Playground and populate it as before: playground := Playground new. teresa := playground add: Triangle new. simon := playground add: Square new. charlie := playground add: Circle new. Comparing Objects Smalltalk compares two objects using boolean expressions. A boolean expression is one that yields a truth value, i.e. true or false. We can use a number of binary messages to perform comparisons. First of all make simon bigger than teresa and charlie and then let's try some comparisons expressions. simon growby: 10. Display the results of the following comparisons: simon radius > teresa radius. simon radius < 100. charlie radius = teresa radius. charlie position ~= teresa position. The final expression is comparing the two positions to see if they are unequal. It's interesting here to note that, in this comparison, we are testing the equality of two points (the previous three comparisons were between numbers). So the comparison messages are not just limited to number objects. But not all objects can be compared since it all depends on whether they respond to the appropriate comparison messages. Try: charlie >= teresa. You got a does not understand walkback because it does not really make sense to compare the magnitude of a circle with that of a triangle. Tip: you might of course decide that you wanted to consider the magnitude of a shape to be its area and file:///c /OADocs/5.htm (1 of 6) [6/2/2000 8:40:09 AM]

25 Control Flow you wanted to be able to use comparison messages based on this fact. Later you'll see how to define new messages for particular classes of object. Hence, if you wish, you'll be able to implement the comparison messages for Playground shapes. All objects do respond to #= and #~=, however: charlie = teresa. simon = simon. simon ~= charlie. Here we are testing to see whether the two shapes are (or aren't) the same object. Tip: by default, the #= message does compare two objects to see if they are one and the same (identical). However, you'll also see that it is possible to change the meaning of a message such that, in the case of shapes, #= could compare the shape areas instead. Testing an Object Some objects understand messages that answer boolean true or false values. You can use these to test to see if an object is of a particular kind or in a particular state. Try these examples: 'this is not an integer' isinteger. 5 between: 0 and: 10. $A islowercase. charlie respondsto: #>=. This last expression asks to see if charlie can understand a #>= message. We've already seen above that it can't so the false answer comes as no surprise. Tip: many testing messages take the form #isxxx. You'll find that this helps to make code easy to read and also gives an indication that the message will answer a boolean value. Controlling the Flow of Execution Now let's put these boolean expressions to some good use. Based on the result of a particular expression we might want to execute or skip a piece of code. This is how it's done in Smalltalk (you don't need to Display it): (simon radius > charlie radius) iftrue: [ MessageBox notify: 'Simon is bigger than Charles']. What's going on here? The boolean expression testing the two radii answers true (because we grew simon slightly earlier). Like everything else, a boolean value such as true or false is still an object and is therefore capable of handling messages sent to it. Here we send it #iftrue: which takes as its parameter a file:///c /OADocs/5.htm (2 of 6) [6/2/2000 8:40:09 AM]

26 Control Flow block of code to execute in the case that the receiver is indeed true. The block of code is enclosed in square brackets []. If the receiver is false then the block does not get executed. There are also additional messages that can be sent to boolean objects along similar lines. "#iffalse:" (charlie color=color green) iffalse: [ "If charlie is not green make him so" charlie color: Color green ]. "#iftrue:iffalse:" (Time now hours>6) "Turn charlie off at night" iftrue: [charlie color: Color yellow] iffalse: [charlie color: Color black]. This message offers the choice between executing one of two blocks of code. You must remember, though, that #iftrue:iffalse: is a single keyword message taking two parameters. Hence there must not be a dot separator after the first block since this would terminate the statement at this point (and you'll subsequently receive an error from the Dolphin compiler). For convenience, there is also the reverse message: "#iffalse:iftrue:" (Time now hours>6) "Turn charlie off at night" iffalse: [charlie color: Color black] iftrue: [charlie color: Color yellow]. Looping As you might expect by now, Smalltalk uses messages to perform looping operations too. 10 timesrepeat: [ teresa moveright: 10 ]. 5 timesrepeat: [ simon growby: 5 ]. The #timesrepeat: message sent to an integer will cause its parameter block of code to be executed that number of times. You can have quite a bit of fun with loops and limited animation in the Playground: [ charlie position x > 0 ] whiletrue: [ charlie moveleft: 10 ] This is interesting; here we have two blocks at work. The #whiletrue: message is sent to a block of code that is expected to answer a boolean result. If this is true then the parameter block is executed. This process is repeated until the receiver block answers false. You've probably guessed already that there is also a similar #whilefalse: message: [ teresa rotation >= 90 ] whilefalse: [ teresa rotateby: 10 ]. Tip: you are probably noticing that the Playground window "flashes" while we are performing these bits of animation. This is because the Playground was not designed for smooth animation which really needs file:///c /OADocs/5.htm (3 of 6) [6/2/2000 8:40:09 AM]

27 Control Flow to be implemented using a process known as "double buffering". You can certainly implement smooth animation using Dolphin, it's just that the Playground has been kept as simple as possible to aid understanding. Note, also, that the speed of each animation step has been deliberately slowed down so you can see it happening. Dolphin is capable of drawing "frames" much faster than you see here. That are two shortcut versions of #whiletrue and #whilefalse that can just be sent to a block of code to cause it to execute repeatedly while it answers true or false respectively. These messages do not require any parameters: [ teresa moveleft: 5. teresa position x > simon position x ] whiletrue. Here we see that the value answered from a code block when it is executed is that of the last expression in the block. The above example moves teresa left and then compares its new horizontal position with that of simon. The result of this comparison is returned as the final result from the block and the #whiletrue message is designed to repeat until this eventually yields false. Iterating Through a Range of Values Sometimes you'll want to loop a number of times and know where you are in the sequence as you do so. For example, let's say that we want to print a list of the square numbers from 1 to to: 12 do: [:n Transcript show: n squared displaystring; cr ]. After evaluating this code in the System Transcript window to see the results. You can send text strings to this window using a #show: message sent to the global variable, Transcript. More importantly, take a look at the #to:do: message and the format of the block it takes as its second parameter. The receiver is an integer which represents the starting value and the first parameter is taking to be the ending value. The block is then executed for this range with each value in turn being passed as a parameter (n) to the block. Yes, that's right; blocks can have parameters too. If a block is to expect one or more parameters then they must be declared immediately after the opening bracket. Each parameter is preceded by a colon and separated by a space. The parameter list is terminated by a vertical bar character. The #to:do: message in the previous example loops through a range of integer values stepping one at a time. If you wish to increase the size of the step then the message #to:by:do: exists for this purpose: 10 to: 120 by: 10 do: [:eachradius simon radius: eachradius ]. 40 to: 220 by: 20 do: [:eachangle simon rotation: eachangle ] In a later chapter you will see how you can iterate over more complicated collections of objects, not just integer ranges. file:///c /OADocs/5.htm (4 of 6) [6/2/2000 8:40:09 AM]

28 Control Flow More Complicated Boolean Expressions So far we have only used boolean expressions containing a single condition. Sometimes it is necessary to use a combination of conditions that make up a more complex expression. Try displaying the results of the following to see if you're working too hard: Time now hours>22 and: [Time now hours<6]. If the current time is between 10 p.m. and 6 a.m., this expression will answer true. By now you should be able to see what's going on here. The #and: message is being received by a boolean value (the result of Time now hours>22) and being passed another condition in a block of code which needs to be evaluated if the receiver is true. The result of the #and: message is that of the combined condition. An #or: message is also available: charlie radius: 40. [simon radius > charlie radius or: [simon radius > teresa radius]] whiletrue: [ simon shrinkby: 10 ]. This shrinks simon to be the same size as the smaller of the other two shapes. Notice that, in this situation, the #or: expression has being enclosed in another block so that it can be repeatedly evaluated by #whiletrue: until the required size is reached. The Beauty of #iftrue: (and friends) If you are used using other computer languages using these messages may look a little odd at first. You're probably used to using something like: if (simon radius > charlie radius) { printf("simon is bigger than Charles") } in which case, the Smalltalk equivalent: (simon radius > charlie radius) iftrue: [ MessageBox notify: 'Simon is bigger than Charles']. looks somewhat "backwards" and perhaps harder to read. I know that I originally thought this when learning Smalltalk for the first time. However, I guarantee that you'll soon get used to it. The beauty comes when you realize that #iftrue: is a message and not part of the Smalltalk language definition at all. The grammar of the traditional language includes the definition of how an "if" statement is formed but Smalltalk needs no such definition. Instead, the control flow is implemented solely with messages. This makes the "language" smaller, more regular, and easier to learn because it has many fewer elements to it. It is also more flexible since you could (if you wished) define new messages to perform similar operations. Of course, all this also applies equally to the other control flow messages: #whiletrue:, #whiletrue, #whilefalse:, #whilefalse, #repeat, #timesrepeat:, #to:do: and #to:by:do:. file:///c /OADocs/5.htm (5 of 6) [6/2/2000 8:40:09 AM]

29 Control Flow What have you learned? In this chapter you have learned about: Simple and complex boolean expressions Comparing two objects Testing objects Conditional execution of blocks of code Looping around blocks of code Iterating through a range of values using a parameterized block Block parameters Please tidy up your workspace and Playground windows before proceeding with the next chapter. Click here to move on to the next chapter or here to go back to the previous chapter. file:///c /OADocs/5.htm (6 of 6) [6/2/2000 8:40:09 AM]

30 Classes and Methods Classes and Methods As you know by now, Smalltalk is an Object Oriented programming language. In this chapter I will introduce you to two concepts that lie at the heart of this; classes and methods. We have already mentioned that all of Smalltalk's objects know what class they are and that it is this class that governs how they should behave. This behaviour is recorded in the class by a number of methods. A method contains the Smalltalk code that determines how a particular message should be executed. This chapter introduces you to classes and methods and the Class Hierarchy Browser, which is the development tool that you use to manipulate them. To an extent, this chapter is largely theoretical, but hang in there since this is important stuff and you only need to wait a short while until the next chapter to get on with some practical Programming in Smalltalk. Classes Let's ask a few objects what class they are. Open a fresh workspace and evaluate the following expressions, displaying the results: 'This is a string'. #(7 'abc' 6.15) 5. Okay, so we've seen that the objects above are classified as a String, an Array and a Point respectively. Now the interesting thing here is that the classes String, Array and Point are also objects too (remember everything is an object in Smalltalk). The fact that class objects have names that begin with an upper case letter should, perhaps, indicate to you that these objects are held in global variables. There are around 600 classes in the basic Dolphin image so there are this number of different types of object, all with different behaviours. Naturally, this number will grow as you program new classes for yourself. Every object is associated with a particular class. In Smalltalk programs we say that every object is an "instance" of its class. This means that 'hello' is an instance of String and 5 is an instance of Point. Question: if a class describes the behaviour of its objects and yet a class is also an object, what describes the behaviour of a class? What is a class object an instance of? The answer is a metaclass. I'm afraid that metaclasses are beyond the level of our current discussion but they are intriguing. Indeed, many computer scientists would consider them to be one of the most intriguing aspects of Smalltalk but, for more information, you'll have to research this for yourself! So what do class objects actually do and what do they contain? One thing classes do is to describe the layout of data in their instances. Most objects have to hold information about their state and they do this using instance variables. We'll learn more about instance variables in a moment but for now, suffice it to say that it is the responsibility of a class object to define the number and names of these variables in its instances. You can find out what instance variables are required by an object by sending the message #allinstvarnames to its class. Try: Point allinstvarnames. This answers an array of strings showing the instance variable names for all Point objects. As you might expect, a Point (which represents a point on a two dimensional Cartesian plane) has variable slots for its x and y co-ordinates. Another thing that classes do is to hold onto pieces of Smalltalk code called methods that describe how instances respond to individual messages. You can query a class to determine what message selectors its instances will respond to. Try displaying the results of: Point allselectors. Point respondsto: #<=. 5) respondsto: #<=. Once you know that a class supports a particular message then you can also ask to see the code for the method that implements the message. Let's take a look at the Smalltalk code that handles the comparison of two points: (Point compiledmethodat: #<=) getsource. file:///c /OADocs/6.htm (1 of 8) [6/2/2000 8:40:20 AM]

31 Classes and Methods The important thing to note here is not so much the code itself, but the fact that Smalltalk objects can be so introspective. You can send them messages to do many things, including asking them to describe how they actually work. This is another important aspect of Smalltalk and is often called reflection since objects have the ability to reflect upon their own behaviour. Class Hierarchy Browser If, every time you wanted to look at some code in your Smalltalk image, you had to evaluate an expression like the one above then things would soon get pretty tedious. Fortunately, there is a much easier way, and this is to use a tool called the Class Hierarchy Browser. To bring up such a browser choose Tools/Class Hierarchy Browser or click on the Browse Classes toolbar button in your workspace. You can use this window to browse through all of the classes in your image. The top left pane allows you to select a particular class to browse. Smalltalk classes exist in a hierarchy, which will be explained in the next chapter in the section on Inheritance. For time being just be aware that the root of this hierarchy is a class called Object and that this is the class that is initially visible in the top left class hierarchy pane of the Class Browser. The easiest way to find a class so that it can be browsed is to select the class hierarchy pane and type Ctrl+F. Try this and you should be prompted to enter the name of a class to search for. Type, Point, to locate this class and display it in the browser. The top right methods pane now contains a list of all the message selectors that Point objects can respond to. The lower pane currently displays the class definition, although there are also two other tabs available to allow it to show either file:///c /OADocs/6.htm (2 of 8) [6/2/2000 8:40:20 AM]

32 Classes and Methods method source code or a comment for the current class. It is using this tool that you will perform most of your programming work with Dolphin Smalltalk. Not only can you browse through existing classes and methods in the system but you can also create new ones. We'll see how to do this in the subsequent chapter but for moment let's just a do some browsing. Methods I've already mentioned that methods are chunks of Smalltalk code that describe to an object how a particular message should be processed. Let's look at some of the methods for class Point. With this class selected in the browser, choose <= in the top right methods pane. The browser will bring up and display the Smalltalk source for the method that handles the #<= comparison message for points. <= anarithmeticvalue "Answer whether the receiver is neither below nor to the right of anarithmeticvalue. A double dispatch of #< with the superclass implementation of #<= would not work here." apoint apoint := anarithmeticvalue aspoint. ^x <= apoint x and: [ y <= apoint y ] This method illustrates a few points that we haven't yet touched upon in the Smalltalk code you've written so far. Let's go through these one by one. Short is beautiful The first thing to note is that the method text is short. This is very often the case with Smalltalk code and you should find that, as a matter of good style, you'll end up writing a lot of rather short methods rather than a few long ones. This makes it very easy for the reader to assimilate how a method works. Also, by breaking down a program into many small chunks, it becomes more flexible. A method is more likely to be re-usable in future situations if it does not try to do too much at once. By re-using pre-written methods your programs will be smaller and easier to maintain. Method header The next important thing is the first line, which forms the method header. This defines the selector for the method (<=) and any parameters that the method takes. Since #<= is a binary message we expect it to take a single parameter which, in this case, we have called anarithmeticvalue. Tip: it is very common in Smalltalk to describe the method parameters using names like anarithmeticvalue, astring, aninteger etc. This is not enforced; it is just a way of helping the reader determine what sort of parameter a particular method expects. Once the parameters have been named at the beginning of the method they can be used like any variable in the body text. In fact, that's not quite true because you're not allowed to assign to them; they are read only. For this reason they are sometimes called pseudo-variables. Temporary variables Some methods, but certainly not all, may require the definition of some temporary variable slots in which working results can be held during execution of the method. If these are needed then they are defined immediately after the method header and are enclosed between vertical bar ( ) characters. This method defines one temporary variable called apoint. Temporaries only exist while the method is executing and any objects that are installed in temporary slots are released when the method completes. file:///c /OADocs/6.htm (3 of 8) [6/2/2000 8:40:20 AM]

33 Classes and Methods Tip: it is convention that all pseudo-and temporary variable names should begin with a lower case letter. Answering a result We have mentioned previously that all message sends answer a result. This must imply that all methods do so too. A result can be returned from a method by pre-fixing an expression with the ^ character. In this example we are answering the result of the following boolean expression: x <= apoint x and: [ y <= apoint y ] You can, in fact, return a result from anywhere within a method; you do not have to hold back until the last line. Also, you don't have to explicitly return anything at all. If you omit to include a return (^) expression then, by default, the method will answer the receiving object. You can learn a lot about Smalltalk just by browsing, so let's take a look at some more methods of class Point. Select the method for #dotproduct:. dotproduct: apoint "Answer a Number that is the sum of the product of the x coordinates and the product of the y coordinates of the receiver and apoint" ^(x * apoint x) + (y * apoint y) This illustrates the definition of a method for a keyword message. In this case it is slightly simpler than the previous example because there is no need to declare any temporary variables. Notice that, in nearly all methods, it is conventional to immediately follow the method header with a comment that describes the purpose of the method. The comment should be indented by one tab space and followed by a single blank line before the body of the method code. Once again this is only convention but following this style will make the code you write easier to understand. Tip: when describing a particular method to someone we often refer to it using a form like Point>>dotProduct:. This is quite important when you realise that the same message selector can be handled by many different classes. Private Methods Now select #x:y: in class Point (Point>>x:y:). x: xcoord y: ycoord "Private - Set the x and y coordinates of the receiver. Primarily intended for instance creation. Answer the receiver." x := xcoord. y := ycoord This shows the definition of a method with two parameters. Note also, that there is no explicit statement returning a value so this means that the method will answer the receiving point when it completes. Also interesting is the fact that, in the comment, the method is marked as being "Private". Some methods are written to be of use only by the original programmer of the class itself and are not expected to be used generally by others. These methods are said to be private to the class and are indicated as such in their method comments. Tip: unlike many other programming languages, Smalltalk does not enforce this idea of method privacy. It is perfectly possible for you to call any private method at any time. What the method author has indicated is that this may not be a good idea, either because the method might have unusual side-effects, or because the method is not guaranteed to be present in future implementations of the class. file:///c /OADocs/6.htm (4 of 8) [6/2/2000 8:40:20 AM]

34 Classes and Methods Named Instance Variables I've already mentioned that objects use instance variables to store their data and that it is an object's class that has knowledge of these instance variables. If you go back to the class definition for Point (click on the Class Definition tab in the browser) you'll see, amongst other things, that it defines the instance variable names for its instances. ArithmeticValue subclass: #Point instancevariablenames: 'x y ' classvariablenames: '' pooldictionaries: '' We'll look at other aspects of this definition in the next chapter but, for the moment, let's just concentrate on how the instance variable names are specified. You can see that this is done using a string containing a list of the variable names separated with spaces. As we saw in a previous example points have two instance variables called x and y. Like all Smalltalk variables, named instance variables are just slots where other objects can be stored. They are not "typed" and therefore not constrained to holding particular classes of object. They are also only directly accessible from methods within the class itself (or its subclasses, which we'll talk about later). Tip: this is a very important precept in Object Oriented Programming; that the internal format of the data of an object must remain hidden at all costs from the users of that object. When you want to know something about an object you send it messages. This allows the implementer of the object the flexibility to change its internal representation at some point in the future and, providing that the set of messages it responds to remains the same, nothing will be broken by such a change. Accessor Methods Since instance variables are not available to clients (users) of an object we needed to provide some means by which their data can be accessed when it is appropriate. We do this by adding methods to the class that are used to get and set the values of the instance variables. Such methods are generally known as accessor methods. Take a look at the following methods in the Point class: x "Answer the receiver's x coordinate" ^x x: anumber "Set the receiver's x coordinate" x := anumber These two methods are used to get and set the value of the receiver's x instance variable. You can also use accessor methods that set multiple instance variables at once or possibly calculate the value of an aspect of the object based on its instance variable contents. For example, take the following two methods: x: xcoord y: ycoord "Private - Set the x and y coordinates of the receiver. file:///c /OADocs/6.htm (5 of 8) [6/2/2000 8:40:20 AM]

35 Classes and Methods Primarily intended for instance creation. Answer the receiver." x := xcoord. y := ycoord r "Answer the receiver's radius (magnitude) in a polar coordinate system." ^(self dotproduct: self) sqrt Categorizing Methods Sometimes a class may contain many methods and to see them all in the Class Browser simultaneously might prove to be confusing. To help with this, Dolphin provides a system whereby each method can be categorised to associate it with other methods having a similar purpose. With the Browser still looking at Point take a look at the top centre categories pane. You'll see that this displays a list of the categories pertaining to the methods held by this class. Initially, All is selected and this means that all methods, no matter what category they belong to, are displayed in the methods list pane to the right in the Browser. Now click on the accessing category and see how the Browser reformats to only display methods that are used to access a Point object's state. We saw most of these when discussing Accessor Methods a few moments ago. There are many different method categories in the Dolphin image and, as you continue to browse the system, you'll rapidly become familiar with them. If you want to return the browser to displaying all methods for a particular class simply ensure that All is selected once again in the list of categories. Indexed Instance Variables For some classes of object, normally those that hold collections of other objects, it is not convenient to simply use named instance variable slots for the object's storage. Hopefully you can see why, since you might need hundreds of separately named variables and even different numbers of variables depending on how many objects you wanted to hold on to. For this reason, certain classes are allowed to have indexed instance variables associated with them. file:///c /OADocs/6.htm (6 of 8) [6/2/2000 8:40:20 AM]

36 Classes and Methods Each of the instance variable slots is accessible using an integer index. This makes an object that uses indexed variables very much like an array in most other programming languages. The index of the first slot is one, so we generally say that Smalltalk indexes are one-based (rather than zero-based). The number of available indexed variables can be altered dynamically by sending the object a #resize: message with an integer parameter containing the number of slots required. This makes it very easy to implement classes that can hold collections of other objects. Smalltalk comes complete with a very powerful set of collection classes and we will discuss these in a later chapter on Collections. For the moment, let's just take a look at the class definition of a common collection class in the base image. Using the Class Hierarchy Browser, find the class called Array (remember you need to select the top left-hand pane and type Ctrl+F). You should see the following class definition displayed: ArrayedCollection variablesubclass: #Array instancevariablenames: '' classvariablenames: '' pooldictionaries: '' The class is being defined using a single message with a rather lengthy selector, #variablesubclass:instancevariablenames:classvariablenames:pooldictionaries:. This message is being sent to the class called ArrayedCollection on which the new class Array is to be based. Note the difference between this definition and the one for Point. There are no named instance variables required here and, in addition, there is the use of variablesubclass: as part of the message selector rather than just plain old subclass:. Now, without going into too much detail at this stage, you just need to take away from this that the Array class is being defined as having a variable number of indexed instance variable slots rather than a fixed number of named instance variables. Classes as Object Factories So far, you've seen how a Smalltalk class is an object that specifies how instances of that class behave. It does this by holding on to all the methods that implement the messages the instance can respond to, and by keeping information about the layout of the instance's data (the instance variables etc.). However, a class object also has an additional useful function; it can act as a "factory" for manufacturing its instances. We've seen this before in Chapter 2: rect := Rectangle origin: 0@0 extent: 10@10. Here we are sending the message #origin:#extent: to the Rectangle class with the expectation that it will answer a new instance of a rectangle. In this way the class is acting like a factory object capable of a manufacturing instances to our file:///c /OADocs/6.htm (7 of 8) [6/2/2000 8:40:20 AM]

37 Classes and Methods specifications and returning them for us to use in any way we see fit. The most common instance creation method is #new which can usually be sent to a class to create a new instance when no additional parameters are required to define it. For example, when we create new shapes to add to a Playground we use something like: playground add: Triangle new. Getting More Help on the Class Hierarchy Browser By now you should be pretty familiar with the basics of using the Class Hierarchy Browser. If you want to learn more about its use then take a look at the online help, which can be accessed by pressing F1 with the browser as the active window. What have you learned? In this chapter you have been introduced to the following fundamental aspects of object-oriented programming: Classes Methods Using the Class Hierarchy Browser to view Classes and Methods Method parameters Method temporary variables Answering a result from a Method Indicating that a Method should be Private Named and Indexed instance variables Browsing Method categories Click here to move on to the next chapter or here to go back to the previous chapter. file:///c /OADocs/6.htm (8 of 8) [6/2/2000 8:40:20 AM]

38 Programming in Smalltalk Programming in Smalltalk This chapter shows you how to add new classes of object to your Smalltalk image and how to program their behaviour by adding methods to them. As you do this you will be extending the capabilities of the basic system. For this reason, you should now be saving your image on a regular basis (to avoid losing these changes) and especially when exiting the Dolphin environment. This is what "programming" is in Smalltalk; producing a new image with the appropriate classes and behaviour to do what you want. A Smalltalk "program" is an image embued with an interacting network of objects. It's a bit like your waking day; when you get out of bed in the morning there is no need to start from scratch again. Instead you are able to pick up exactly where you left off the previous day, with all the objects in your life ready to go. This is what happens when you start a Smalltalk image; everything is there just as it was when you last shut the image down. Tip: if you are from a more "traditional" programming background you may be confused by this at first and wonder where a Smalltalk program starts. There is no main entry point. When your program loads, the image will already contain the initial set of objects ready to go. This chapter teaches you how to "program" in Smalltalk. The Animal game In this chapter we will build an implementation of a simple animal guessing game. The game will ask you to think of an animal and it will then try to guess what it is by asking a series of questions. If it turns out that it does not know the animal you are thinking of then the program will ask you to tell it what it was so it can learn this new animal for future games. I originally saw this game written a long time ago in a compendium of BASIC programs (written when BASIC was far from "Visual"). It was the first learning program that I'd seen and I was amazed that something so simple could appear to be "intelligent". I thought it would be interesting to see what it looked like in Smalltalk, so here it is. The full game has been provided in a package called Animals. At this stage, you might like to load this into your image using the Package Browser just so you can see what it is intended to do. You should find the package in the Samples/Animal Game directory beneath the location where Dolphin is installed. Double-click over Animals.pac to install it into your image. Tip: If you can't locate the package on your local computer then you can download it from the web. Please make sure you save this file in a Samples/Animals Game subdirectory beneath your Dolphin installation. Once the package is in your image, then go to a workspace and evaluate: Animal playgame. You will be asked to think of an animal and then to respond to questions about it. Initially, the game only knows one animal (a dog) so the first round will be pretty boring. If the game does not know the animal you are thinking of then it will ask you to enter its name so it can learn it for next time. You will also be asked to think of a question that distinguishes the new animal from one that is already in the database. Make sure you follow the instructions here and enter a question that fits the format requested. When you get tired of expanding the Animal game's knowledge base then be sure to uninstall the package from your image so that you can follow the tutorial in this chapter. You can do this using the Package Browser's, Package/Uninstall menu command. file:///c /OADocs/7.htm (1 of 23) [6/2/2000 8:40:34 AM]

39 Programming in Smalltalk How it works Before we use the Dolphin development system to design and build this game it might be useful to look at how it works. Let us consider exactly what this game does. It builds up a knowledge base of the animals that it knows about and, in order for it to be able to guess sensibly, this must also contain questions that enable it to distinguish between one animal and another. In this version of the game each question has a yes or a no answer. This might lead us to think that a "tree" of objects something like the following can represent the knowledge base: This is an inverted tree with its root(s) at the top of the diagram. The brown Question nodes represent the branches and the leaves are at the Animal nodes in green. Pick one of the animals in the diagram (Dog, Snake, Eagle or Horse) as your guess and follow the decision tree through from the root of the tree starting at the brown arrow. file:///c /OADocs/7.htm (2 of 23) [6/2/2000 8:40:34 AM]

40 Programming in Smalltalk So it seems that we can build our animal knowledge base from two classes of object; Animals and Questions. We will also have to hold the tree's root object (always a Question) somewhere so we can get access to it in order to start the game. You'll see how to do this later. Class Inheritance Right, let us now try to add the Animal class to our image. Before we do this, we need to know a little bit about class inheritance. Open a Class Hierarchy Browser and select Object in the class hierarchy pane at the top left. If Object is the only class that is visible in this pane then double-click it to expand the display until it appears as below. As you can see, the browser is displaying some of the many classes that already exist in the image. These classes exist in a hierarchy where each class (apart from Object) is a child of some parent. This hierarchy is important since it governs how any particular class can "inherit" some of its parent's functionality. For example, with Object selected, the browser will be displaying all of the methods defined for this class in the method pane at top right. Now click on Boolean and you'll see a list of its methods instead. As you can see, the number of methods that appear to be available for Boolean is much smaller than for Object. However, this is not the definitive list. Since Boolean is a "subclass" of Object it inherits all of the latter's methods, which means that Boolean instances can respond to all of these messages too. Tip: Actually, this is rather a false example since instances of Boolean can never exist. It is what is called an abstract class. If you double-click on Boolean to expand it and display its subclasses you'll see that it has two; True and False. Instances of these classes do exist and they can respond to any of the messages defined for Object and Boolean as well as those defined for themselves. As you can no doubt see, this inheritance of behaviour can be a great time saver. By choosing an appropriate place in the hierarchy to define a new class you can save yourself having to rewrite, and duplicate, code which has already been written and tested previously. file:///c /OADocs/7.htm (3 of 23) [6/2/2000 8:40:34 AM]

41 Programming in Smalltalk Superclass and subclass Okay, now for a couple of definitions. We have seen that a class can have a number of child classes beneath it. These are known as its subclasses. It therefore follows that the parent of a particular class should equally be known as its superclass. Every class apart from Object will have one, and only one, superclass but may have many subclasses. Object is unique in not having a superclass because it is the root of the hierarchy. Tip: Once again I've introduced a slight simplification here. There actually can be other classes like Object which exist at the root of the hierarchy and therefore have no superclasses. This is quite an advanced topic so we shall not dwell on it here. Is-a and Contains-a Relationships So, back to Animal. Where in the class hierarchy should we choose to create this class? The first thing to consider is what sort of information will each instance of Animal hold. Looking at the knowledge base diagram above we can see that each animal must at least know its name; i.e. what sort of animal it is. This will be in the form of a Smalltalk text String such as: 'Dog', 'Cat', 'Horse' etc. So, a possible location in the class hierarchy that we might consider would be to make Animal a subclass of String. To look at this decision in more detail, find the String class in the Class Hierarchy Browser (remember you can do this using the Class/Find menu command) and take a look at the methods that are defined for all Strings. If we make our Animal class a subclass of String then we will inherit all of these methods. This may, or may not, be what we want. Think about it; does it make sense for an Animal to understand messages such as #>= and #asnumber etc? No, not really! What we should actually be asking is whether an Animal "is a String" or whether it, in fact, should "contain a" String. This is one of the fundamental decisions that software designers make when they are performing an "object oriented analysis" on a design problem. Often a problem is complex enough that file:///c /OADocs/7.htm (4 of 23) [6/2/2000 8:40:34 AM]

42 Programming in Smalltalk it is worth drawing a diagram of the object model and this will illustrate the relationships between the various objects in the system. The relationships are often described as Is-a and Contains-a relationships. It is my suggestion, therefore, that an Animal should contain a String and not be a subclass of one. So, we still haven't yet decided exactly where Animal should be subclassed in the overall hierarchy. In these situations it is best just to start off with your class being a direct subclass of Object (it is to represent an object after all). This is a very good default starting point. The great thing about Smalltalk is that, if you should later discover that there is a more suitable superclass somewhere in the image, then it is really easy to refactor and move your class to this new location in the hierarchy. Creating a class Let's now create the Animal class as a subclass of Object. To do this, select the superclass Object in the Class Hierarchy Browser and choose Class/New. You will be prompted to enter a name for the class you want to create; in this case Animal. You'll then see that the browser has created your class and will also display a Smalltalk definition of it in the Class definition pane at the bottom. Tip: The area at the bottom of the Class Hierarchy Browser can display of one of three panes depending on which tab is selected. You can choose from Method source, Class definition and Class comment. At present the Class definition pane will have been selected automatically to show you the definition of the class that has just been created. We hinted in the previous chapter that the contents of this pane contains a Smalltalk expression that could be evaluated in any workspace to create the class. Look closely and you'll see that the message #subclass:instancevariablenames:classvariablenames:pooldictionaries: is being sent to Object in order to do this. It's convenient that the browser saves us the typing and composes and evaluates this expression for us. file:///c /OADocs/7.htm (5 of 23) [6/2/2000 8:40:34 AM]

43 Programming in Smalltalk Adding instance variables Now let's go back to consider the data that each instance of our Animal class must hold. We mentioned before that we need to be able to hold the name of the animal as a String and we will therefore need an instance variable to do this. So, let's add an instance variable called name. Using the mouse, place the text insertion cursor in the text string that immediately follows instancevariablenames: and type the variable name. Object subclass: #Animal instancevariablenames: 'name' classvariablenames: '' pooldictionaries: '' In order to commit this change into the image simply type Ctrl+S or choose Accept from the Workspace menu. Congratulations, you have just added your first class to your Dolphin image. You can change the class definition at any time simply by modifying it in the Class definition pane and accepting the change. Now might be a suitable time to save your image. Adding methods Our next task will be to use the Class Hierarchy Browser to add some method definitions to the Animal class. Adding accessor methods One of the things about object-oriented programming in general, and Smalltalk in particular, is that it is not possible to gain access to the data stored in an object except by means of methods written in the class. For example, we will want to be able to set and retrieve the value in the name instance variable slot of an Animal and, to do this, we will need to write a couple of methods. These are known as accessor methods. We will want to add methods for #name and #name:. Select the Animal class in the Class Hierarchy Browser and choose the Method/New command. This sets up the browser ready to receive a new method definition in the Method source pane. Enter the following method: name "Answer the name of the receiver" ^name Choose Workspace/Accept or type Ctrl+S to accept this new method definition into the image. You'll see that, after the browser compiles the method, it is then redisplayed in the source pane in coloured text. The different colours identify different parts of the language and quite soon you'll find this makes the methods easier to read. The method that we have just added included the ^ symbol to indicate that a value should be returned from the method. The intention of this particular accessor method is just to return the value held in the name instance variable. Now let us add another method to set the value of this instance variable. Once again choose Method/New and enter and accept the following code: file:///c /OADocs/7.htm (6 of 23) [6/2/2000 8:40:34 AM]

44 Programming in Smalltalk name: astringname "Private - Initialize the name of the receiver to astringname" name := astringname This method receives one parameter that I've given a name of astringname to identify it. Notice how the name chosen for this parameter can indicate to the reader of the code what type of object is acceptable here, e.g. a String. This is purely done for readability, so at no time will the system insist that actually only a String is allowable. It can be a useful practice to get into the habit of naming parameters in this way so that someone browsing through the methods of your program in future will have a better idea how to use them. The sole purpose of this method is to assign the contents of the passed parameter to the name instance variable. Notice that I have chosen to label the method as Private within the method comment. It was discussed in the previous chapter that Smalltalk does not enforce such method privacy but, once again, this is useful documentation for any programmer intending to make use of our Animal class. What it indicates is that, under normal circumstances, one would not expect to call this method directly. Tip: You may be wondering what this method is for if it is not intended to be directly called. We'll see the reasoning for this later. Categorising methods We mentioned before that it is useful to place methods in categories to help identify them, and it is best to do this as you enter each method. There are several ways in which the Class Hierarchy Browser can help you categorise methods but the simplest is probably to ask it to suggest a category for you. Select the method in question, say #name, and choose Method/Suggest category. You will be prompted with a dialog of category suggestions that the browser thinks are suitable for this particular method. Those categories listed with a + symbol adjacent to them can be expanded. Yes, that's right, categories can exist in a hierarchy too. All you need to do is to double click the category that you think is most appropriate for your method and it will automatically be added into it. In this case, since we are dealing with an accessor method it would seem appropriate to enter it into the accessing category. Tip: You can also bring up the category suggestion dialog by clicking over the method in question with the right mouse button. This will pop-up a context menu for the method and you can choose Suggest category from within this. file:///c /OADocs/7.htm (7 of 23) [6/2/2000 8:40:35 AM]

45 Programming in Smalltalk It is always possible, and indeed quite likely, that the category suggestion box may not contain a category that you consider to be suitable for your method. If this happens, then click Cancel to dismiss the box and use the Method/Category command to bring up the following alternative dialog that displays a list of all the categories currently in the image. Tip: Once again this dialog can also be brought up from the context menu for the method. Simply right-click over the method and choose the Category command. From this dialog you can assign your method to any one of the existing categories in the system and, if you still don't think any of these are appropriate, you can create a new category by clicking the New button. Time for a Test The good thing about Smalltalk is that it's really easy to test things quickly. Why don't we create an instance of Animal and see what we can do with it so far. In a workspace evaluate: myanimal := Animal new. "Display the following" myanimal name. "Now give it a name" file:///c /OADocs/7.htm (8 of 23) [6/2/2000 8:40:35 AM]

46 Programming in Smalltalk myanimal name: 'Dog'. "And display the name again" myanimal name. These simple tests show how we can create a new instance of an Animal, assign a name to it and then query the name again. Nil Okay, look back to that test that we just did. Immediately after we had created the fresh instance we queried its name and got back a (perhaps) surprising result; nil. This is a special value that Smalltalk uses to indicate that a variable slot has not yet been initialized. Nil is actually an object in its own right (if you ask it its class it will answer that it is an instance of UndefinedObject). In Smalltalk everything is an object - right down to the concept of nothingness! Nil can be used for more than just testing whether something is uninitialized. You'll also find it useful in your own programs when you want to represent the concept of something being in an undefined state. Instance creation methods By default, all classes respond to a #new message and answer an instance of the class. We used this fact in our previous test. We didn't have to write the #new method ourselves since all classes inherit this via their superclass chain. Tip: You might expect to find this method in the Object class. However, it isn't there, but rather it's in class Class. Why not use the browser to take a look? However, using #new to create an instance of Animal isn't really ideal since, as we've seen, we end up with an animal that has a nil name. It would be much better if we could ensure that as each instance is created it is properly initialized with a valid String name. We can do this by adding an instance creation method that takes as its parameter the name of the animal to be created. Such a method is not applicable to an instance of Animal but rather to the class itself. For this reason it is called a class method (as opposed to the instance methods we have created so far). To create a class method you must first select the Class tab in the class hierarchy browser. The browser will then switch to displaying the class methods of the current class rather than its instance methods. Now add the following method to the class side: name: astringname "Answer an instance of the receiver with astringname" ^self new name: astringname As you can see, this creates a new instance of Animal and then sends it a #name: message to initialize its name. To indicate that this is indeed an instance creation method, you should add it to the instance creation category. This time try right-clicking over the method and choosing Category from the pop-up context menu that appears. file:///c /OADocs/7.htm (9 of 23) [6/2/2000 8:40:35 AM]

47 Programming in Smalltalk Tip: Now it might become apparent why we marked the #name: method on the instance side of Animal as being private. The intention is that this method will only be called from the class method of the same name. We don't expect that an Animal instance, once it has been created, will ever have its name changed so we indicate this by suggesting the method is private and therefore it should not be called explicitly. Representing an object as text There are many situations where we might want to display one of our objects as a text string. By convention, Smalltalk provides a number of methods defined in Object for this purpose. #displaystring and #displayon: It is generally assumed that these messages can be used to display any object as an end-user would expect to see them. The first, #displaystring, will answer a String representation of the object. The second takes a Stream as its only parameter and outputs the textual representation of the object to this stream. Streams are the subject of a later chapter so we won't go into too much detail about them here. The thing to note, however, is that #displaystring is usually implemented in terms of #displayon:. This means that if we need to change the way an object is represented as end-user text we normally only need to implement a #displayon: method. First of all, let us see how an Animal responds to #displaystring by default. Try executing the following example in a workspace. tiger := Animal name: 'Tiger'. "Display this" tiger displaystring. Now, displaying this just as a "an Animal" is surely a little lacklustre. Let's override the default implementation of #displayon: (found in Object and which provides the grunt work for #displaystring) to at least report the name of the animal involved. Add the following method to Animal. IMPORTANT: Since this is to be an instance side method, make sure you click the Instance tab in the browser first. displayon: astream "Answer the name of the receiver prepended by 'a' or 'an' as appropriate" aoran aoran := name first isvowel iftrue: ['an '] iffalse: ['a ']. astream nextputall: aoran; nextputall: self name. Use the Suggest category facility to add this method to the displaying category. Now try testing #displaystring again and you should see a more user-friendly representation of the tiger: "Display this" tiger displaystring. Writing a method like this in a derived class, which has the same name as a method in a superclass, is known as overriding the original method. This is another important aspect that forms part of object-oriented programming. file:///c /OADocs/7.htm (10 of 23) [6/2/2000 8:40:35 AM]

48 Programming in Smalltalk #printstring and #printon: These messages are used in a similar way to the #displaystring and #displayon: methods except that they are intended to create a textual representation of an object as a developer (a rather than an end-user) would wish to see it. The default implementation of these methods in Object will merely tell the developer what the class of the object is (e.g. an Animal). Now let us override #printon: to also display the animal's name along with its class. printon: astream "Answer the name of the receiver as a developer would wish to see it." super printon: astream. astream nextput: $(. self displayon: astream. astream nextput: $). Again use Suggest category to categorise the method, this time adding it to the printing category. To test this in the workspace, display the result of evaluating the following. "Print this" tiger printstring. If everything has gone according to plan this should print as "an Animal(a Tiger)". Whenever you add a new class to your image you should probably consider overriding one or more of the #displayon: and #printon: methods. You might want to do this even if you don't need to represent your object as text in your initial design; it's very likely that this could become a requirement at sometime in the future. Self and Super In the last method we added we managed to slip in a couple of new and very important concepts; of those of self and super. If, in a method, we want to send another message to the receiving object then we use the special word self to represent the object. Take a look at the #printon: method again to see how this works. We want to use the ability of #displayon: to print-out the animal's name as a part of the overall representation. We do this by sending the #displayon: message to self. Perhaps a more difficult concept to explain is that of super. We use this when we want to send a message to the receiver but we don't want any local declaration (in the receiver's class) of the corresponding method to be executed. Therefore, when you send a message to super, the system will begin its search for the method to execute, not in the class of the receiver, but in its superclass. This is very commonly used when overriding a method. Often you will want to inherit the existing functionality from the overridden method and yet augment it with additional code of your own. This is exactly what is happening in the #printon: method we have just written. Question: What would have happened in this method if we had inadvertently sent #printon: to self rather than super? It's a sure bet that you'll find self and super cropping up extensively in the code that you write from now on. file:///c /OADocs/7.htm (11 of 23) [6/2/2000 8:40:35 AM]

49 Programming in Smalltalk Creating the Question class We mentioned earlier that the Animal game would probably require two classes. So far we have added a class called Animal and we have put in place the basic functionality for this. Now let us create the second of the two classes; Question. So what do we know about how a Question object should behave? Well, look back to the diagram at the beginning of this chapter illustrating the data structure for a typical Animal game. In the same way that each Animal object has a name we will require that each Question will also need to hold onto a text string which is the question to be asked. In addition to this, each Question object must also be able to indicate which branch of the tree to follow given a yes or no response to the question. So it seems sensible to assume that we might need three instance variables, text, yes and no. Thinking about it, we might also decide that the most sensible superclass for Question is again to be Object. Bearing all this in mind you should follow the following steps to add this new class to your image. Add class Question as a subclass of Object Select Object in the Class Hierarchy Browser. Now use the Class/New menu command to create the Question subclass of Object. Add the new instance variables and re-compile the definition as indicated below. Object subclass: #Question instancevariablenames: 'text yes no' classvariablenames: '' pooldictionaries: '' Add the accessor methods First of all add the following methods to be able to get the values of the three instance variables. yes "Answer the branch in the knowledge tree to take as the result of a 'yes' answer to the receiver's question." ^yes no "Answer the branch in the knowledge tree to take as the result of a 'no' answer to the receiver's question." ^no file:///c /OADocs/7.htm (12 of 23) [6/2/2000 8:40:35 AM]

50 Programming in Smalltalk text "Answer the receiver's question as a text String" ^text It will certainly be useful to be able to access the values of these variables separately. However, once an instance of Question has been created we should never need to set the values of these variables again. Therefore, it makes sense that we should be able to use a private method to set all of these variables at once during instance creation. We'll use the following method to do this: text: astring yes: yespath no: nopath "Private - Set the text of the receiver to astring and the yes and no branches to yespath and nopath respectively. This is a bit tricky. At the end of this operation we want the receiver to have completely swapped its identity with the original nopath. This is a bit of a kludge (since there are better ways to insert the receiver in the knowledge tree at the right point) but it is the simplest solution for this example program." text := astring. yes := yespath. no := self. self become: nopath Okay, so you've spotted the final line and want to know what that is all about. Well, to be honest, the use of the #become: message is beyond the real scope of this chapter and its use in this example program is only due to the fact that I wanted to shorten the program to make it easier to understand. However, for those who are interested, the tip below explains why it is here. Tip: Imagine an existing knowledge tree for the game (I suggest you refer back to the original diagram) and we have got to the situation where the computer does not know the animal in question. Let us assume for the sake of this description that the computer believes you are probably thinking about an "eagle" but, in fact, you are thinking about a "sparrow". What we need to do is to create a new Animal object representing the "sparrow" and also to create a new Question that is capable of distinguishing the two animals. When we have completed linking these two new objects into our knowledge base the original Question that led to the "eagle" node will now have to point to the new distinguishing Question node. The easiest way to do this is to ask the two objects (the "eagle" and the new question) to swap identities. This is what #become: does. Make sure you add these methods to the accessing category. Adding an instance creation method Now we need a class method to use when creating a Question instance. IMPORTANT: Make sure you set the Class Hierarchy Browser into Class mode before adding this method otherwise it will override the one you have just created on the instance side. file:///c /OADocs/7.htm (13 of 23) [6/2/2000 8:40:35 AM]

51 Programming in Smalltalk text: astring yes: yespath no: nopath "Answer an instance of the receiver (a Question) having astring as it's text and leading to the nodes at yespath and nopath as the result of those answers to its question." ^self new text: astring yes: yespath no: nopath This method must go into the instance creation category. Printing and displaying a Question The following methods allow for a Question to be represented as text from the point of view of an end-user and developer respectively. You can use the category suggestion feature of the browser to place these methods into their correct categories. IMPORTANT: Place the browser back into Instance mode before adding these methods. displayon: astream "Answer the name of the receiver as a user should see it. For this we append a question mark." astream nextputall: self text; nextputall: '?'. printon: astream "Answer the name of the receiver as a developer would wish to see it." super printon: astream. astream nextput: $(. self displayon: astream. astream nextput: $). file:///c /OADocs/7.htm (14 of 23) [6/2/2000 8:40:35 AM]

52 Programming in Smalltalk Creating a class variable to hold the knowledge base Sometime ago we mentioned that we would need to hold the root of the knowledge base in a variable, if only so the game will know where to get hold of it when it starts. Now is the time to create and initialize this variable. We could, of course, choose to use a global variable for this purpose. However, it is usual to frown upon global variables since they may clash with similarly named variables in another application. Fortunately there is an excellent alternative; to use a class variable. We have seen how instance variables can be used to hold data that is associated with a particular instance. Well it is also possible to create another type of variable that is associated with a particular class object. It's very easy to add class variable slots to your class by using the Class Hierarchy Browser. Let us choose to add a class variable called KnowledgeBase to the Animal class. First of all select Animal in the browser and then choose the Class definition tab to display the existing definition. Modify this as shown below and accept the change using Ctrl+S. Tip: It is conventional for the names of class variables to begin with an uppercase letter. This new variable can be used like any other but only within the scope of the Animal class. This means that you can use it in any methods (either instance or class) that are defined for Animal or its subclasses. You will not, however, be able to successfully reference the KnowledgeBase variable from any other class or workspace. This means that you would not be able to reference it from within the Question class, for example. The good thing about this additional level of privacy compared with true globals means that no other class or program can modify this variable inadvertently. Tip: Sometimes you might want to allow methods outside the normal scope to be able to access a class variable. This is quite possible, and is simply a matter of defining some accessor methods in much the same way as you would for instance variables. The only difference, of course, is that the accessor methods you define for a class variable must be defined as class methods rather than instance ones. Anyway, in our Animal game will only need to reference the KnowledgeBase from within the Animal class so we'll have no need for any accessor methods. Initialize the Animal class The next job is to initialize the KnowledgeBase so that it has a suitable root object for the game to start with. If we add this initialization as part of a class method then we can re-use it when we want to clear down the game and start afresh (i.e. forget all the game has learnt). So, add the following class method to Animal and place it in the initializing category. file:///c /OADocs/7.htm (15 of 23) [6/2/2000 8:40:35 AM]

53 Programming in Smalltalk initialize "Initialize the Animal game knowledge base. To start with we only know about Dogs" KnowledgeBase := self name: 'Dog' As the method suggests, we'll start off with the game only knowing about dogs. Now, in a workspace, evaluate the following to actually perform the initialization. Animal initialize. Tip: The inclusion of an #initialize class method has a special additional significance for when you choose to save out your work so it can be imported into someone else's Dolphin image. As a class is loaded into a new image the system checks to see if an #initialize class method exists and, if it does, this is executed automatically. Consequently, this is a great way to ensure that class variables (and suchlike) are properly set up. Wiring the game together So now we have most of the elements in place for our Animal game and it just remains to add a few methods that wire all the pieces together. First of all, since we are going to be adding methods to both the Question and Animal classes, I'd like to introduce a bit of nomenclature that will help avoid any confusion as to exactly where the methods belong. Take a look at the following: Animal>>thisMethod Indicates that thismethod belongs on the instance side of the Animal class Animal class>>thismethod Indicates that thismethod belongs on the class side of the Animal class Question>>thisMethod Indicates that thismethod belongs on the instance side of the Question class Question>>thisMethod Indicates that thismethod belongs on the instance side of the Question class This >> symbol is commonly used as a means of documenting that a method belongs to a particular class you'll find that we use it quite often from now on in this guide. Asking the questions When a game is in progress much of the action will be to do with the computer asking you questions. As the game traces through the knowledge tree, at any particular time it will be looking at either a Question node or, if it thinks it knows what the animal is, an Animal node. Do you remember how you traced through a possible game scenario in the original diagram? If so, you'll see how the computer must pose a question to the human player at each stage. For example: file:///c /OADocs/7.htm (16 of 23) [6/2/2000 8:40:35 AM]

54 Programming in Smalltalk "Does it have wings?" - for a Question object or "Are you thinking of an Eagle?" - for an Animal object. Now the interesting thing here is that we can write the game so that it does not need to be aware of what type of node it is dealing with at any one time. It can go around just sending an #ask (say) message to each node that it comes across and, providing we implement a suitable #ask method in each of the Animal and Question classes everything should operate just fine. As it turns out, specifying object behaviour in this way is a fundamental part of object-oriented programming. We call this Polymorphism or Polymorphic behaviour. The key thing is that different classes of object can respond to the same method in different ways. This is great because it means that the sender need not be concerned about what type of object the receiver is, merely that it responds appropriately to the message being sent. So let's add our polymorphic (it's a great word that) #ask methods to Question and Animal. Place them in the operations category. Question>>ask "Ask the receiver's question and continue the game appropriately depending on the answer that is received" (MessageBox confirm: self displaystring caption: 'The animal you''re thinking of...') iftrue: [ self yes ask ] iffalse: [ self no ask ]. Tip: Note the double quote '' marks used to obtain a single quote character within the caption text string. You must use these to indicate to the Smalltalk compiler that the string is not actually to be terminated at this point. In the above method we are using a MessageBox to put up a simple dialog displaying the question text together with a suitable caption and a couple of buttons to allow the player to answer yes or no. Hopefully, you can now see how the game logic follows the yes or no branches in the knowledge tree based on the player's answer to the question. Next is the Animal>>ask method. When this is called, the computer thinks it has a sensible guess for the animal (at least it has no more questions to ask anyway). Consequently, it must ask if the guess is correct and, if so it wins the game. If not, it prompts for a new Animal to be created with the real answer and for a new Question that will distinguish this from the original guess. You'll notice that there are some new messages being sent for which we have not yet designed the methods but, don't worry, we'll get to these in just a moment. file:///c /OADocs/7.htm (17 of 23) [6/2/2000 8:40:35 AM]

55 Programming in Smalltalk Animal>>ask "Ask whether the receiver is the animal that the player is thinking of. If it is then the game is over. If it is not then prompt for the true answer and install it and a question which will distinguish this new animal from the receiver. This allows the game to learn." newanimal newquestion (MessageBox confirm: ('Are you thinking of ', self displaystring, '?')) iftrue: [ MessageBox notify: 'I guessed your animal correctly.' caption: 'GREAT, I WIN' ] iffalse: [ newanimal := Animal prompt. newquestion := Question prompttodistinguish: self from: newanimal ]. (MessageBox confirm: 'Do you wish to play again?' caption: 'I''m, getting better all the time...' iftrue: [ Animal playgame ]. Prompting for a new Animal So we saw in the last method a need to have a way of creating a new Animal by prompting for its name. Well here it is. Animal class>>prompt "Prompt for a new animal to add to the game" newname [newname isnil or: [newname isempty]] whiletrue: [ newname := Prompter prompt: 'Tell me, what animal were you thinking of? It was a...' caption: 'So, you win...']. ^self name: newname As you can see the method makes use of a class called Prompter, which can be used to prompt the user to enter a text string. This is checked for validity and then used to create a new Animal instance using our original #name: method. Since the #prompt method answers a new instance, it makes sense to place it in the instance creation category. Remember too that it is a class method so you must have the Class tab clicked in the browser when you create it. Tip: The method is complicated slightly by the fact that we have to check that Prompter does answer a valid name. If we didn't do this you'd find that the game would pretty soon go horribly wrong. Prompting for a new Question And, almost finally, we need a method to prompt for a new Question object. file:///c /OADocs/7.htm (18 of 23) [6/2/2000 8:40:35 AM]

56 Programming in Smalltalk Question class>>prompttodistinguish: anoldanimal from: anewanimal "Answers an instance of the receiver (a Question) that will distinguish between anoldanimal and anewanimal. The question should be phrased such that the answer is 'yes' for anewanimal" questiontext [questiontext isnil or: [questiontext isempty]] whiletrue: [ questiontext := Prompter prompt: ('Now, please enter a question that will answer Yes for anewanimal displaystring, ' and No for ', anoldanimal displaystring) caption: 'Now, so I can learn about ', anewanimal displaystring ]. ^self text: questiontext yes: anewanimal no: anoldanimal Once again we have to use a Prompter and check to see that a valid response is received from the player before creating the new instance. Playing the game We are now ready, with the addition of one last method, to play our Animal game. What we need is a single method to start the game off. Just for a little fun I've left the method box below blank, so see if you can guess how the Animal>>playGame should be written. Don't worry if you can't get it, just click on the tell me how link and I'll show you how it's done. Animal class>>playgame "Start a new Animal game" tell me how So now, to play the game just evaluate: Animal playgame. With a bit of luck you should be able to run through a few sessions with the game so that it learns some new animals. There is a pretty good chance, however, that something may have gone wrong as you worked through this chapter so here is a list of checkpoints. Emergency checklist Check that you have the following methods defined: Animal class>>initialize Animal class>>name: Animal class>>playgame Animal class>>prompt file:///c /OADocs/7.htm (19 of 23) [6/2/2000 8:40:35 AM]

57 Programming in Smalltalk Animal>>ask Animal>>displayOn: Animal>>name Animal>>name: Animal>>printOn: Question class>> prompttodistinguish:from: Question class>>text:yes:no: Question>>ask Question>>displayOn: Question>>no Question>>printOn: Question>>text Question>>text:yes:no: Question>>yes Also check that you have initialized the game by evaluating: Animal initialize Packaging the Animal game Up to now you have just used the Package Browser to load existing packages into your Dolphin image. Since we have just created what is effectively a new Smalltalk application that we might wish to distribute to others, now is an opportune time to learn how to use the Package Browser to create a new package. Creating a new package Open the Package Browser which will display the existing packages in your system. file:///c /OADocs/7.htm (20 of 23) [6/2/2000 8:40:35 AM]

58 Programming in Smalltalk You can create a new empty package by choosing Package/New and then entering an appropriate package name. In this particular case I have chosen the name "Animals". You can now choose to add the two classes (Animal and Question) that comprise the game in one of two ways. 1. Go to the Class Hierarchy Browser and select each class in turn and, for each, pull down the packages drop down in the toolbar in order to move the class into the new package you have created. 2. Alternatively, you can drag each class from the Class Hierarchy Browser using the mouse and drop it over the appropriate package in the Package Browser. As you do so you should see the class appear in the Classes pane of the latter. Tip: In fact, a package can include objects other than just classes. For instance you can include individual methods in a package by dragging the methods file:///c /OADocs/7.htm (21 of 23) [6/2/2000 8:40:35 AM]

59 Programming in Smalltalk from the Class Hierarchy Browser and dropping them over the correct package in the Package Browser. For more details press F1 at any time within the Package Browser. Creating a package comment It is usual to include a comment with the package that explains what it is for and how to start using it. In order to do this select the Package comment tab and type an appropriate comment in the workspace pane at the bottom of the Package Browser. You can save the comment by choosing Workspace /Accept or by typing Ctrl+S. Saving the package After you have created a new package or changed any of its contents you must save it in order to export the classes from your image. If you are about to save the package for the first time you may want to choose a particular directory in which the package file (with.pac extension) will reside. You can do this using the Package/Save as command. As you might expect, on subsequent saves you can just use Package/Save or the Save toolbar button to export the contents. Unloading a package from your image Should you wish to remove the Animal game from the Dolphin image you can do this by using Package/Uninstall (but you should know this already). What have you learned? This chapter has been a pretty long haul but, if you have made it this far, you can relax in the knowledge that you've now created your first Smalltalk program and packaged the classes up so they can be distributed to others. Let us now recap on what you should come away with from this chapter. This is what you have learned here: Class Inheritance Superclasses and Subclasses Abstract Classes How to create a class using the Class Hierarchy Browser Adding methods to a class Categorising methods Overriding methods in a Superclass Polymorphism Representing undefined values using nil Sending messages to self and super Class variables Initializing classes Packaging an application with the Package Browser file:///c /OADocs/7.htm (22 of 23) [6/2/2000 8:40:35 AM]

60 Programming in Smalltalk Click here to move on to the next chapter or here to go back to the previous chapter. file:///c /OADocs/7.htm (23 of 23) [6/2/2000 8:40:35 AM]

61 Experiments with Simple Windows Experiments with Simple Windows By now you'll want to try some experiments that produce graphical results. That's what this first tutorial is about; to open some windows and draw in them. Opening a window and drawing on its canvas In Dolphin, windows are represented by subclasses of View. For example, a top-level window will be an instance of the class ShellView. Let's open a ShellView and play around. w := ShellView new show. Evaluate this in a Workspace. A new workspace local variable will be created to hold a new ShellView window. A window will appear on your desktop and we can use the variable, w, to talk to it. Open a Class Hierarchy Browser and find the View class; you can use the Class/Find command to do this. Select the geometry category to filter only those methods concerned with manipulation of a window's geometry. You'll see that there are methods to position a view and to change its extent. Try evaluating the following statements individually: w position: 0@0. w extent: 250@150. w height: 200. w x: 60. In order to draw on a window, you need to ask for its canvas. All drawing operations are performed on a canvas; if you are a Windows programmer you'll recognise this as being equivalent to a Device Context. To ask for a drawing canvas send the #canvas message to any View. This returns an instance of the Canvas class. If you locate this within the Class Hierarchy Browser you can see the operations available for painting on a canvas. Try evaluating: w canvas ellipse: (Rectangle origin: 0@0 extent: 250@150). w canvas text: 'Hello from Dolphin' at: 50@50. Don't worry, at this stage we don't expect the ellipse to quite fill the window; we'll deal with that later. Try the ellipse again but this time changing the border and fill colours. This is done by setting the pen and brush of the canvas respectively. Evaluate the following cascaded sequence:: w canvas pen: Pen red; brush: Brush gray; ellipse: (Rectangle origin: 0@0 extent: 250@150) You might like to further investigate the Pen and Brush classes in the browser to see how to create instances with other colours, widths and fill styles etc. Notice that if you minimize and restore your window, or otherwise cause it to be repainted, then the result of all that hard drawing effort vanishes. We'll see how to add some permanence to this in just a moment. Creating a new View subclass We want to create a new type of window with some additional behaviour, that is, to paint an ellipse and a "Hello" greeting as its contents. In Smalltalk, to add new behaviour you create a new subclass of an existing class. We'll want our new window, once again, to be a top level window. So we need to inherit the behaviour of the ShellView class. Let's create a subclass of ShellView. ShellView subclass: #Greeting file:///c /OADocs/8.htm (1 of 3) [6/2/2000 8:40:57 AM]

62 Experiments with Simple Windows instancevariablenames: '' classvariablenames: '' pooldictionaries: '' Tip: You can either evaluate the above statement directly to create the class or, more easily, you can use the Class/New command in the Class Hierarchy Browser. Using the latter, just enter the class name (Greeting) into the prompter that appears and the definition will be automatically generated for you. Once a class has been created you can immediately instantiate an instance of it. w := Greeting new show. Obviously the window looks identical to a standard ShellView. Now we need to add a additional behaviour. Each time that an area of a window is exposed, Windows sends a WM_PAINT message to that window asking for the area to be repainted. Dolphin maps the WM_PAINT message to an onpaintrequired: method that can be overridden in any View subclass. Let's copy the code we experimented with before into an onpaintrequired: method for Greeting. Tip: Use Method/New in the browser to create a space for the new method. Type (or copy) in the code and choose Workspace/Accept to compile it. onpaintrequired: apaintevent "A portion of the receiver window has been exposed and needs repainting. The supplied apaintevent holds details about the exposed area. Within #onpaintrequired: you MUST ask for a Canvas from apaintevent (not the receiver window) to paint the contents on." canvas canvas := apaintevent canvas. canvas pen: Pen red; brush: Brush gray; ellipse: (Rectangle origin: 0@0 extent: 250@150); text: 'Hello from Dolphin' at: 50@50. If the compilation is successful, the code immediately becomes active without any need to restart the application. As soon as you cause your Greeting window to be repainted the onpaintrequired: method will be executed. We could make our message somewhat more flexible if it resized as the window size was changed. Basically this means changing the onpaintrequired: handler (and we can jazz it up slightly at the same time) but it also requires that we intercept Windows' WM_WINDOWPOSCHANGED message routed by Dolphin to an onpositionchanged: method. onpositionchanged: apositionevent "The receiver has been positioned or resized. Force a repaint of the entire client area. We need to do this in cases where changing the extent of a View alters the way in which it is painted (rather than just the area that is repainted)" self invalidate. ^super onpositionchanged: apositionevent. In order to make use of this we need to modify the #onpaintrequired: method once again. onpaintrequired: apaintevent "A portion of the receiver window has been exposed and needs repainting. The supplied apaintevent holds details about the exposed area. Within #onpaintrequired: you MUST ask for a Canvas from apaintevent file:///c /OADocs/8.htm (2 of 3) [6/2/2000 8:40:57 AM]

63 Experiments with Simple Windows (not the receiver window) to paint the contents on." canvas box textbox box := self clientrectangle. canvas := apaintevent canvas. canvas pen: Pen red; brush: Brush gray; ellipse: box; font: (Font name: 'Arial' pointsize: 24); settextalign: TA_CENTER TA_BASELINE; setbkmode: TRANSPARENT; settextcolor: Color red; text: 'Hello from Dolphin' at: box center. With luck your greeting will appear as below: Click here to move on to the next tutorial. file:///c /OADocs/8.htm (3 of 3) [6/2/2000 8:40:57 AM]

64 A Scribble Pad Component A Scribble Pad Component Here's a simple Scribble pad that can act as a tutorial for creating any new MVP component triad. We won't go through the creation process step by step but what we'll do is to talk through the design issues whilst you simultaneously look at the pre-written code. So, if it is not already present in you image, load in Scribble.pac from Samples\Scribble using the Package Browser and let's go. Model First In creating a MVP component triad I always create the model first. Programmers using "visual" tools very often draw the user interface part first but this can lead to topsy turvy designs in my experience. First of all, lets see the Scribble pad in action. Evaluate: Scribble show The basic data object for Scribble is an InkStroke. Find this class in the Class Browser. Instances of InkStroke represent the points that the mouse has tracked over for a single stroke (down to up). The actual model for a completed scribble will obviously be a collection of these InkStroke objects. I've chosen the Scribble model to be a ListModel holding a collection of InkStrokes. I could have chosen to create a new class (say ScribbleModel) to represent this but, in this simple example, it would have had no methods and would just over complicate the design. You can always create such a new class later if you require. Tip: You might do this if you wanted to add specific methods to ScribbleModel such as #compress (to compress the ink data for example). Anyway let's have a quick test of our InkStroke and the model used to hold it. file:///c /OADocs/9.htm (1 of 3) [6/2/2000 8:41:07 AM]

65 A Scribble Pad Component stroke := InkStroke new. stroke addpoint: addpoint: addpoint: model := ListModel with: OrderedCollection new. model add: stroke. model do: [:each each drawon: View desktop canvas ]. This should scribble annoyingly over the top left of your desktop. Drawing the Model in a View So we have the M part of our MVP triad. It's a ListModel that must hold (only) a series of InkStrokes. The next stage is to decide on a view that is capable of representing this model data onscreen. Very often one can use an instance of an existing class to show model data. For example, we could choose to use a ListBox or ListView to show our ListModel. This would work but would not give the desired effect, merely a list of textual representations of the InkStrokes. No, I'm afraid we are going to have to create a new View subclass to draw our model successfully. I have created a ScribbleView class as a subclass of View. Take a look at it now. When designing a view, remember that it is responsible for displaying it's model's data and any changes to it. It is not usually responsible for handling the user input; this is the jurisdiction of the associated presenter. The ScribbleView overrides #onpaintrequired: to draw its model. It also observes (in #model:) a number of events triggered by the model to cause it to be redrawn when the model changes. Let's test the ScribbleView by creating one, setting it's model and placing it inside a dummy ShellView. view := ScribbleView new. view model: model. shell := ShellView new show. shell addsubview: view. Now for the Presenter Since we now have the MV out of MVP, next is the presenter. It's duty is to intercept user input, interpret it, and map it as changes to the model. Let's create a Scribble presenter class. We could create this as a subclass of ListPresenter since we know that our model is to be a ListModel too. However, ListPresenter also contains a bunch of code that is to do with selections which is (currently) meaningless for Scribble, so we create it as a direct subclass of Presenter The class method #defaultmodel instantiates a default ListModel to use when a new instance is created. Notice that Scribble does not override the class side #defaultview methos so it will expect to find a suitable view associated with it in the Resource Manager with the name "Default view". We must install an instance of ScribbleView into the Resource Manager with this name. You can easily do this by executing: Scribble addview: ScribbleView asresource: 'Default view'. file:///c /OADocs/9.htm (2 of 3) [6/2/2000 8:41:07 AM]

66 A Scribble Pad Component You can then edit this resource in the View Composer by finding it in the Resource Browser and double clicking. You might want to do this to set default background colors or other such stuff. Now you can instantiate a Scribble component in a default shell by evaluating: scribble := Scribble show. Scribble away and write your name or something. Accessing Ink You can access the ink data using #model and save it away for later. inkdata := Scribble model. Now close the original window. You could, of course, choose to save the ink using an STB filer some other persistency mechanism Now try puttng the ink back into another Scribble presenter. scribble := Scribble showon: inkdata. You'll see the ink re-appear and can add further to it. For some extra magic, without closing this new window, open another on the same model data. Scribble showon: inkdata. Now when you draw in either component the other updates at the end of each stroke. This completes the tutorial discussion of the Scribble Pad MVP component. Click here to move on to the next tutorial. file:///c /OADocs/9.htm (3 of 3) [6/2/2000 8:41:07 AM]

67 Etch-a-Sketch Etch-a-Sketch Now let's see how to create a simple Etch-a-Sketch component that emulates the popular child's toy. We will use an instance of Scribble inside this component, so if you haven't already installed the Scribble package you should do so now. As in the last tutorial, we'll use this session as a discussion of the design issues while you look through the pre-built code. This is contained in Samples\Etch-a-Sketch\Etch-a-Sketch.pac so load this into your image now using the Package Browser. It's probably best at this stage to play with an instance of EtchASketch to see how it works. Evaluate: EtchASketch show. The instance appears in a dummy shell and you can use the horizontal and vertical scroll bars to draw in the sketch arena. Now let's go through the code bit by bit to see how it hangs together. Once again: Model First As always with MVP, I believe it is best to decide on the model objects first. So what should the model be for an instance of EtchASketch? Well, presumably it is the picture being drawn. In this case, since we intend to reuse Scribble, the model can be the same as the one that we chose for the latter, i.e. a ListModel holding an OrderedCollection of InkStrokes. Creating the View Once again, the next stage is to decide on a view that is capable of representing the model visually. Okay, we already have a ScribbleView class that can do this but for Etch-a-Sketch we need something more. In particular, we are going to need controls to represent the horizontal and vertical drawing "knobs", and we might also want to make it look in basic appearance more like a real Etch-a-Sketch toy. From within the Resource Browser open the file:///c /OADocs/10.htm (1 of 4) [6/2/2000 8:41:20 AM]

68 "Basic Etch-a-Sketch" view associated with the EtchASketch class. Let's explore what you see:. Etch-a-Sketch First notice, that the view is an instance of ContainerView. With Scribble with had to create a new class, ScribbleView to represent it onscreen. Here, however, we have decided that composing instances of existing view classes together can actually create a suitable view instance. This, of course is the job of the View Composer. So, the ContainerView is a composite containing: an Horizontal scroll bar named "leftrightknob" a Vertical scroll bar named "updownknob" a ScribbleView named "sketchpad" a StaticText containing the title "Etch-a-Sketch" file:///c /OADocs/10.htm (2 of 4) [6/2/2000 8:41:20 AM]

69 Etch-a-Sketch The important thing to realize about naming these views is that the names must correspond to appropriate presenter objects to which the views will eventually be connected. But more about this later. Using a Layout Manager to arrange the views How are the views arranged? I have used a layout manager associated with the ContainerView to ensure that the sub-views will be appropriately positioned whenever the container is resized. Select the ContainerView and take look at its #layoutmanagerclass aspect. You'll see that this has been set to BorderLayout. A BorderLayout can automatically arrange up to five sub views within its associated container. These can be arranged at #north, #south, #east, #west and #center positions depending on the #arrangement aspect set for each sub-view. Look at the #arrangement for each of the sub-views: leftrightknob: #south updownknob: #east sketchpad: #center Etch-a-Sketch: #north These tell the BorderLayout how to automatically position the objects. However, you'll notice that there is also a border keeping some of these objects away from the very edge of the container. This is set by the #insets aspect of the ContainerView itself. If you look, you'll see that this is a Rectangle: 20@0 corner: 20@20. This governs the available area in which the layout manager can operate. The fact that the top of this rectangle is set to 0 indicates that the #north object (the Etch-a-Sketch static text) can be aligned completely at top edge of the view. Background Colours To get the red border effect, the #backcolor aspects of the ContainerView and the StaticText are set to an appropriate red color. Creating the Presenter Class That's all there is to the view for Etch-a-Sketch. It is saved down, named "Default view" and associated with the appropriate presenter, in this case EtchASketch. So, how do we go about creating this presenter class? First we must decide where to subclass EtchASketch in the Presenter hierarchy. Since we have decided that the view for EtchASketch is a ContainerView this, almost invariably, determines that the presenter should be a subclass of CompositePresenter. CompositePresenters have the ability to maintain a collection of sub-presenters and they inherit the ability to automatically connect these to same named sub-views within their overall attached view. Since our EtchASketch component does not have to be limited to use within a shell or dialog window we have chosen to subclass the presenter directly under CompositePresenter (rather than Shell or Dialog). This gives it the ability to be easily reused in future as part of any other composite we may wish to create. Once you have decided where to create a presenter class, the best thing to do first is to add the essential class methods #defaultmodel and #defaultview. For #defaultmodel, we have already decided that the model will be (like Scribble) a ListModel that holds an OrderedCollection of InkStrokes. Once again we have chosen to use the name "Default view" for the view resource and this means we can rely on inheriting the class side #defaultview method. file:///c /OADocs/10.htm (3 of 4) [6/2/2000 8:41:20 AM]

70 Etch-a-Sketch Sub-Presenters Now look at the class definition of EtchASketch. There are three instance variables (updownknob, leftrightknob and sketchpad) that will be used to hold sub-presenters that eventually will be connected to their matching sub-views. The lastlocation variable is necessary to hold temporary information about the last drawing location. The sub-presenters are created in a method called #createcomponents. This is usually the first method you will write when creating any CompositePresenter subclass. Note that the sub-presenters are named to match their associated views. We mentioned earlier that we would be re-using the Scribble component for the sketch area of EtchASketch and it is here that this instance of Scribble is created. Notice too, that we have chosen to make the "knob" components instances of NumberPresenter. This is because they will contain numeric values that can be changed by the user interface; in this case by the scroll bars. However, as far as the presenter logic is concerned, it need not know exactly what type of view will eventually be connected. If, in future, we decide to create a new "KnobView" class to represent a more realistic input device than a scroll bar, then we should be able to place instances of this into the Etch-a-Sketch view and everything will work directly, without having to change any of the presenter code. Wiring up the Sub-Presenter Events The next method to write, for any composite presenter that requires it, is #createschematicwiring. This method is used to clip onto any interesting events that the sub-presenters may trigger and redirect them to appropriate event handling methods in this class. Here, we want to intercept changes made to the "knob" values (as the scroll bars are moved) and direct them to our #onknobchanged method which will perform the drawing. The #onknobchanged method is fairly straightforward. It finds the values of the left and right "knobs" and creates an appropriately scaled Point (the scroll bar views, by default, return values between 0 and 100 and these are scaled to the full extent of the sketchpad view). This is then used to create an InkStroke that represents the line from the last location to this new location. This is added to the receiver's model. Connecting the models Now, there is just one last thing to consider. We have arranged, courtesy of the #defaultmodel class method, for an appropriate model object to be installed into an instance of EtchASketch when it is created. The #onknobchanged method will draw new lines into this model as the "knobs" are twiddled. However, in order for the drawing to appear in the sketchpad area, we need to ensure that this EtchASketch model is also that of the Scribble sub-presenter. This is made so by overriding the #model: method on the instance side. You've already seen EtchASketch in use but another interesting demonstration, to show the flexibility that MVP allows when sharing model objects, is to create an EtchASketch on the same model as a Scribble pad. Try this: scribble := Scribble show. EtchASketch showon: scribble model. This completes the tutorial discussion of the Etch-a-Sketch component. Click here to move on to the next tutorial. file:///c /OADocs/10.htm (4 of 4) [6/2/2000 8:41:20 AM]

71 Creating an Application Tutorial Creating an Application This chapter is a tutorial session that takes you through the steps needed to build a simple application in Dolphin Smalltalk using the Model-View-Presenter framework. How to use the Patterns The Dolphin education centre comes with a set of Patterns that will help you with many common programming issues. The patterns have been designed in a hierarchy such that you can choose a suitable entry pattern and this will take you through the steps, and possibly sub-patterns, that are necessary to accomplish a task. In order that you become used to using the patterns, as well as learning how the Dolphin environment hangs together, this tutorial provides links to the various pattern pages at appropriate points. If you follow one of these links, then once you have become familiar with the pattern description you should use your browser's Back button to resume the tutorial at the point you left off. PersonalMoney - a simple account manager The task in this tutorial is to produce a simple personal accounts manager which we'll call PersonalMoney. This application will: Maintain a list of accounts for a user Enable a user to write cheques against an account Maintain the balance for any account The application will have a graphical user interface consisting of shell windows and dialog windows that allow a user to communicate with the account information and invoke account operations. The application will store the account data within the Smalltalk image but also will provide facilities to save and restore this data to and from disk. file:///c /OADocs/11.htm (1 of 2) [6/2/2000 8:41:27 AM]

72 Creating an Application Tutorial Creating a Project We are now ready to start building the application using the Application pattern. The first step is to create a package for the PersonalMoney application using the Dolphin Package Browser. Choose Tools/Package Browser to open the Package Browser window. If you do not want to interactively follow this tutorial you can load a sample version of the application from the file Samples\PersonalMoney\PersonalMoney.pac using File/Open. Otherwise use File/New to create a new package and enter a suitable name, say, PersonalMoney.pac. All of the classes and resources that you create for the PersonalMoney application will be associated with this package which will allow them to be exported from your image and then imported into another image at a later date Click here to move on to the next section of this tutorial or here to go back to the previous tutorial. file:///c /OADocs/11.htm (2 of 2) [6/2/2000 8:41:27 AM]

73 Designing the Domain Models Creating an Application Designing the Domain Models The next stage in the Application pattern is to design the domain level classes. This stage is perhaps somewhat different from other visual programming systems which encourage you to build an application starting with the user interface. Although it is possible to build an application this way in Dolphin, we would recommend against it since it can obfuscate the design process. It is much cleaner to design and build the core of the system, the domain model, first and then to add the user interface classes subsequently. Indeed, this is just as easy as the standard "visual method" because the Smalltalk development environment provides tools to directly test the domain classes as you go; you do not need to build a user interface to do this. We're going to add 3 domain level classes for our application. PersonalMoney. This class will maintain and owner's name and a list of accounts. PersonalAccount. This class will maintain account details and a list of transactions on that account held in date order. It will also provide a facility to calculate the current balance of the account. PersonalAccountTransaction. Instances of this class represent transactions on PersonalAccounts. Each one holds details such as the amount, the description, and the date of the transaction. For each of the classes below follow the New Class pattern. PersonalMoney The PersonalMoney class can be subclassed from Model. This will usually be the norm for domain model classes that are liable to trigger update events when aspects of them change. You might choose a different superclass if you need to inherit specific behaviour from another class or if your model does not trigger any update events (in this latter case a more suitable superclass might be Object). Define the PersonalMoney class as follows: Model subclass: #PersonalMoney instancevariablenames: 'owner accounts ' classvariablenames: '' pooldictionaries: '' The owner instance variable will hold a string containing the user's name, and the account variable will hold a collection of account objects. The next responsibility is to add any specialized instance creation methods that the class may require. We have two instance variables here that require initialization and the normal method to ensure that this occurs is to add an initialize instance method to the class and arrange that this is called from whenever an instance is created. In fact, the Model superclass contains a new method that sends #initialize to all newly created instances, therefore we only need to add the initialize functionality since it will be called by default. initialize "Private - Initialize the receiver" accounts := ListModel with: OrderedCollection new. We initialize our accounts collection with a ListModel rather than just an OrderedCollection because we'll want to receive change notifications as the list is updated. If this was not the case then a plain OrderedCollection would do just fine. The next step is to add Accessor Methods to allow other objects access to the contents of the instance variables. owner "Answer the owner of the receiver" ^owner. file:///c /OADocs/12.htm (1 of 6) [6/2/2000 8:41:38 AM]

74 Designing the Domain Models owner: astring "Set the owner of the receiver to astring" owner := astring. accounts "Answer the accounts collection" ^accounts There is no need to add an accessor method to set the accounts collection since this is only ever necessary during the initialization of an instance. Consequently this can be considered a private operation which does not warrant such a method. Tip: as you add each method to the system using the Class Hierarchy Browser it's a good idea to categorize them as you go. An easy way to do this is to use the Method/Suggest Category command. Choose this with a method selected in the browser and you will be presented with a list of potential categories for the method. If none of these is suitable you can add a new category using the New button. The next duty, according to the New Class pattern, is to define the classs behaviour. A useful method to add to all new classes is #printon: to print the contents of an object in a form suitable for a developer to read. This will aid later testing and debugging. printon: astream "Append, to astream, a String whose characters are a description of the receiver as a developer would want to see it." self basicprinton: astream. astream nextput: $(. self owner printon: astream. astream nextput: $). We are also going to need to add new PersonalAccounts to the application and also to allow them to be removed. addaccount: apersonalaccount "Add apersonalaccount to the collection of accounts owned by the receiver Answers apersonalaccount" ^self accounts add: apersonalaccount removeaccount: apersonalaccount "Remove apersonalaccount from the collection of accounts owned by the receiver. Answers apersonalaccount" ^self accounts remove: apersonalaccount Notice the use of descriptive parameter names for these methods which aids readability. PersonalAccount Let's now create a class to represent each account. Model subclass: #PersonalAccount instancevariablenames: 'name accountnumber initialbalance transactions currentbalance' classvariablenames: '' pooldictionaries: '' Each account instance holds some details about the account, such as the name, the account number and the initial balance, together with a list of all the transactions on the account. These variables obviously require initialization to place an instance file:///c /OADocs/12.htm (2 of 6) [6/2/2000 8:41:38 AM]

75 Designing the Domain Models into a known state. initialize "Private - Initialize the receiver" name := 'New account'. initialbalance := currentbalance := 0.0. transactions := ListModel with: (SortedCollection sortblock: [:x :y x date <= y date]) Once again our list is to be a ListModel, but this time it wraps a SortedCollection capable of sorting the account objects that it holds based on their dates. Now add the following accessor methods. accountnumber "Answer the account number of the receiver" ^accountnumber. accountnumber: astring "Set the account number of the receiver to astring" accountnumber := astring. currentbalance "Answer the calculated current balance of the receiver." ^currentbalance currentbalance: anumber "Set the current balance of the receiver to anumber." currentbalance := anumber. self trigger: #currentbalancechanged. initialbalance "Answer the account initial balance of the receiver" ^initialbalance. initialbalance: anumber "Set the account initial balance of the receiver to anumber" name initialbalance := anumber. self calculatecurrentbalance "Answer the account name of the receiver" ^name. name: astring "Set the account name of the receiver to astring" name := astring. transactions "Answer the transactions collection" ^transactions. Again there is no need to provide a method to set the transactions ListModel. file:///c /OADocs/12.htm (3 of 6) [6/2/2000 8:41:38 AM]

76 Designing the Domain Models The following methods add behaviour to the class. printon: astream "Append, to astream, a String whose characters are a description of the receiver as a developer would want to see it." self basicprinton: astream. astream nextput: $(. self name displayon: astream. astream nextput: $,. self accountnumber displayon: astream. astream nextput: $,. self currentbalance displayon: astream. astream nextput: $). displayon: astream "Append, to astream, a String whose characters are a description of the receiver as a user would want to see it." self name displayon: astream. astream nextput: $-. self accountnumber displayon: astream. addtransaction: apersonalaccounttransaction "Add apersonalaccounttransaction to the collection of transactions owned by the receiver. Answers apersonalaccounttransaction" self transactions add: apersonalaccounttransaction. self calculatecurrentbalance. ^apersonalaccounttransaction. removetransaction: apersonalaccounttransaction "Remove apersonalaccounttransaction from the collection of transactions owned by the receiver. Answers apersonalaccounttransaction" self transactions remove: apersonalaccounttransaction. self calculatecurrentbalance. ^apersonalaccounttransaction. calculatecurrentbalance "Calculate and set the current balance of the receiver. Add the total of all the actual amounts to the initial balance" balance balance := self transactions inject: self initialbalance into: [:total :each total + each actualamount ]. self currentbalance: balance. PersonalAccountTransaction One more class to go and then we can do some experimentation. Now will define the class that represents a transaction on a PersonalAccount. Model subclass: #PersonalAccountTransaction instancevariablenames: 'date description amount isdebit ' classvariablenames: '' pooldictionaries: '' file:///c /OADocs/12.htm (4 of 6) [6/2/2000 8:41:38 AM]

77 Designing the Domain Models Each transaction holds a descriptive String and a numeric amount, together with the date of the transfer. The isdebit flag is a boolean to indicate whether the transaction is a debit or a credit operation on the account. initialize "Private - Initialize the receiver" date := Date today. description := String new. amount := 0.0. isdebit := true. The initialization and accessor methods are again straightforward. amount "Answer the amount of the receiver" ^amount. amount: anumber "Set the amount of the receiver to anumber" date amount := anumber. "Answer the date of the receiver" ^date. date: adate "Set the date of the receiver to adate" date := adate. description "Answer the String description of the receiver" ^description. description: astring "Set the description of the receiver to astring" isdebit description := astring. "Answer true if the receiver is a Debit transaction" ^isdebit. isdebit: aboolean "Set the receiver to a Debit transaction according to aboolean. If aboolean is true then the receiver is treated as a credit" isdebit := aboolean. It will be useful to provide a proper method that answers the effective amount for the transaction taking in into consideration the isdebit flag. actualamount "Answer the actual amount of the receiver taking into consideration whether it is a debit or credit transaction" ^self isdebit iftrue: [ self amount negated ] file:///c /OADocs/12.htm (5 of 6) [6/2/2000 8:41:38 AM]

78 Designing the Domain Models iffalse: [ self amount ]. Again we provide a printon: method, but this time we also include a displayon: method to determine how a transaction will appear when presented to the user as text. By default it is this method that is used to display an object within a list or text view on the screen. printon: astream "Append, to astream, a String whose characters are a description of the receiver as a developer would want to see it." self basicprinton: astream. astream nextput: $(. self displayon: astream. astream nextput: $). displayon: astream "Append, to astream, a String whose characters are a description of the receiver as a user would want to see it." self date displayon: astream. astream nextputall: ': '. astream nextputall: self description. astream nextputall: (self isdebit iftrue: [' - debit '] iffalse: [ ' - credit ']). self amount displayon: astream. Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/12.htm (6 of 6) [6/2/2000 8:41:38 AM]

79 Testing the Domain Models Creating an Application Testing the Domain Models Now we have completed the first pass at designing our domain model classes, it is a suitable time to test the functionality. Evaluate the following in a Workspace. a := PersonalMoney new. a owner: 'My Name'. b := PersonalAccount new. b name: 'My Current Account'. b accountnumber: 'ABC345'. b initialbalance: 500. You can inspect either of these two instances to ensure they are correct, then add the account to the money application: a addaccount: b Next create one or more transactions and add these to the account: c := PersonalAccountTransaction new. c description: 'Brown Shoes'. c amount: b addtransaction: c. When done, you can ask for the current balance of the account as follows (remember to display the answer): b currentbalance As you can see it is easy to exercise all of the functionality in your domain classes from a Smalltalk workspace before progressing to the user interface programming. It is good practice to clean up any variables that you create during testing (such as a, b, c here) to avoid them holding on to unwanted instances of your test objects. The easiest way to do this is simply to close the workspace in which they were declared. However, in this case these temporary values may be useful for trying out your user interface later. Keep them around now, but remember to close the workspace later on when you've finished. Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/13.htm [6/2/2000 8:41:46 AM]

80 Designing the User Interface Creating an Application Designing the User Interface The next task is to add the interface components to our application. This involves adding Presenter-View user pairs to the domain models that we have so far created in order to complete a series of MVP triads. It is from this plugging together of different objects that Smalltalk achieves its great flexibility even with only single inheritance available in the language. An MVP application can achieve its goal in one of two ways, either by the creation of it is usually fairly apparent which to choose in any given situation. basic or composite triads, and So far we have created the domain models for our application. What we require from our user interface is a method of editing the various aspects of each of these models. It seems likely, therefore, that for each model we'll need to build a composite MVP triad in which each part of the composite is responsible for editing a single aspect of the overall model. Let's start by creating a presenter-view pair for a PersonalAccount. Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/14.htm [6/2/2000 8:41:55 AM]

81 PersonalAccountShell: a Presenter for PersonalAccount Creating an Application PersonalAccountShell: a Presenter for PersonalAccount We want to create a presenter that displays a PersonalAccount as its model and allows for its various aspects to be edited. This should be a top level shell window so a suitable superclass for our new class will be Shell. Shell subclass: #PersonalAccountShell instancevariablenames: 'namepresenter accountnumberpresenter initialbalancepresenter transactionspresenter currentbalancepresenter ' classvariablenames: '' pooldictionaries: '' The definition includes instance variables to hold separate presenters which will handle the editing of each of the relevant aspects of the model. These sub-presenters are initialized in the createcomponents method. createcomponents "Private - Create the presenters contained by the receiver" super createcomponents. namepresenter := self add: TextPresenter new name: 'name'. accountnumberpresenter := self add: TextPresenter new name: 'accountnumber'. initialbalancepresenter := self add: NumberPresenter new name: 'initialbalance'. transactionspresenter := self add: ListPresenter new name: 'transactions'. currentbalancepresenter := self add: NumberPresenter new name: 'currentbalance'. For each model aspect a suitable presenter is created and added to the shell composite. The sub-presenters are given names to identify them when the view is connected; each sub-view will be given an identical name so that presenter-view pairs can be matched and connected together. The choice of presenter to use for each aspect depends on the effective type of the aspect's value. Each of the aspects will be accessed using a ValueAspectAdaptor so that #value and #value: can be used to get and set its value. For this reason, each of the presenters that will be used to edit a model aspect will inherit from the class ValuePresenter. Take a look at the subclasses of ValuePresenter to see what's available. Obviously, if there was nothing yet available that was suitable then you'd have to create a new ValuePresenter subclass to do the job. In this case the existing subclasses will be sufficient. The next task is to specify how the model is connected to the presenter. model: apersonalaccount "Set the model associated with the receiver." super model: apersonalaccount. namepresenter model: (apersonalaccount aspectvalue: #name). accountnumberpresenter model: (apersonalaccount aspectvalue: #accountnumber). initialbalancepresenter model: (apersonalaccount aspectvalue: #initialbalance). currentbalancepresenter model: (apersonalaccount aspectvalue: #currentbalance) aspecttriggersupdates. transactionspresenter model: (apersonalaccount transactions). First of all the PersonalAccount is assigned as the actual model of our composite using the super message send. Then the models of all the sub-presenters are set to be ValueAspectAdaptors on the appropriate aspects of the account. Tip: a shortcut to creating a ValueAspectAdaptor is to send #aspectvalue: to the account object specifying the name of the file:///c /OADocs/15.htm (1 of 3) [6/2/2000 8:42:03 AM]

82 PersonalAccountShell: a Presenter for PersonalAccount aspect you want. Take a look at the one special case here; creating the ValueAspectAdapator for #currentbalance. Once created the adaptor is sent #aspecttriggersupdates. This is important since it informs the adaptor that the aspect it's connected to will trigger its own update notifications whenever it is changed. Do you remember the #currentbalance method we wrote for PersonalAccount? PersonalAccount>>currentBalance: anumber "Set the current balance of the receiver to anumber." currentbalance := anumber. self trigger: #currentbalancechanged See that, it triggers #currentbalancechanged when the balance is assigned to. If we didn't send #aspecttriggersupdates to the ValueAspectAdaptor we create for this aspect then it would believe that it was responsible for triggering these notifications itself. This would result in two notifications for each change in the current balance. Hardly the end of the world but irritating nonetheless. The next step is to wire together the sub-presenters using the standard Smalltalk event notification mechanism. This wiring is implemented by overriding the createschematicwiring method. It is only necessary to override this method if you wish to respond to events triggered by your sub-presenters. In this case we want to send an #edittransaction message to the PersonalAccountShell when a transaction in the transactions list is double-clicked. createschematicwiring "Private - Create the trigger wiring for the receiver" super createschematicwiring. transactionspresenter when: #actionrequested send: #edittransaction to: self. The last essential task that must be considered when creating any presenter is to define class methods, defaultmodel and defaultview. The former should answer an object which the presenter will use as its model in cases where this is not specified explicitly (which is the most likely situation). In this case we answer a default instance of PersonalAccount. The defaultview method must answer a resource name to use to load a default view. The defaultview method inherited from Presenter class specifies a view name, not surprisingly, of 'Default view'. This is suitable for most purposes so we just have to make sure that this matches the name under which the actual view is saved by the View Composer. defaultmodel "Answer a default model to be assigned to the receiver when it is initialized." ^PersonalAccount new Tip: remember these are class methods. Now add the remainder of the accessing methods for PersonalAccountShell. selectedtransactionornil "Answer the currently selected transaction or nil if there is none" ^transactionspresenter selectionornil selectedtransactionornil: apersonalaccounttransactionornil "Sets the currently selected transaction to apersonalaccounttransactionornil. If nil if there will be no selection" ^transactionspresenter selectionornil: apersonalaccounttransactionornil hasselectedtransaction "Answer true it there is a currently selected transaction in the receiver" ^transactionspresenter hasselection file:///c /OADocs/15.htm (2 of 3) [6/2/2000 8:42:03 AM]

83 PersonalAccountShell: a Presenter for PersonalAccount One of the fundamental ways in which a user can interact with a model is by issuing commands from a menu or toolbar. It is the presenter's role to intercept these commands and translate them into modifications to the model. Commands are parameterless messages and we need to provide the appropriate methods for handling them. edittransaction "Edit the selected transaction" #todo "Write this later". newtransaction "Prompt for a new transaction and add it to the receiver's model" #todo "Write this later". removetransaction "Removes the current transaction from the receiver's model" transaction transaction := self selectedtransactionornil. transaction notnil iftrue: [ self model removetransaction: transaction ]. These methods should go in the commands category. We will implement the #todos after we have created a suitable dialog for editing transactions. Tip: you can use a #todo symbol to mark methods where something needs to be modified or implemented in future. You can then browse for references to the #todo symbols to find all the outstanding tasks. Remember the period following the comment, otherwise the statement will not be valid Smalltalk syntax. By default any command that is implemented by a presenter will be enabled when the menu is pulled down. To change this default behavior and enable or disable commands directly, you must implement a querycommand: method. querycommand: acommandquery "Enters details about a potential command for the receiver into acommandquery" super querycommand: acommandquery. (#(edittransaction removetransaction) includes: acommandquery command) iftrue: [ acommandquery enabled: self hasselectedtransaction ] Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/15.htm (3 of 3) [6/2/2000 8:42:03 AM]

84 Drawing a View for PersonalAccountShell Creating an Application Drawing a View for PersonalAccountShell The time has come to use the View Composer to create a suitable view for editing a PersonalAccount object. This is the view that we're going to attempt to draw. When you're creating a view it is important to bear in mind details about the presenter to which the view will be attached., in particular, you will need to know the types and names of the sub-presenters which must to be connected to sub-views that you're drawing. In PersonalAccountShell we have: Sub-presenter type Connection name Model aspect TextPresenter 'name' #name TextPresenter 'accountnumber' #accountnumber NumberPresenter 'initialbalance' #initialbalance NumberPresenter 'currentbalance' #currentbalance ListPresenter 'transactions' #transactions To open the View Composer so we can start painting choose Tools/View Composer. file:///c /OADocs/16.htm (1 of 6) [6/2/2000 8:42:11 AM]

85 Drawing a View for PersonalAccountShell A floating toolbox of available view resources will also be displayed. This is illustrated below. Since we are going to create a shell window that will eventually be attached to a presenter which is a subclass of class Shell we'll want to see all the available view's for this class in the toolbox. Scroll down until you find Shell - Default view in the toolbox list and then drag this resource and drop it over the Composing Arena in the View Composer. Voila, a blank shell window to act as canvas for our view painting. Tip: You can also use File/New Shell View to open a blank window for painting. Using the Published Aspect Inspector First of all we need a caption for the shell view. The two panes at the bottom right of the View Composer act as an inspector displaying the published aspects of the selected view. In the left hand pane of this Published Aspect Inspector, select caption and move to the right pane to edit its value. Type a suitable title for the shell, say, "Personal Account Details", and you'll see this appear in the shell's title bar as you type. file:///c /OADocs/16.htm (2 of 6) [6/2/2000 8:42:11 AM]

86 Drawing a View for PersonalAccountShell Tip: the right-hand pane of the Published Aspect Inspector changes according to the type of the aspect selected in the left pane. For text based aspects these are often updated as you type, but not always. Sometimes you must hit the Enter key or de-select the aspect before it is updated. Other aspects will be presented to you in different ways. A boolean value, for example, will display as a check box. All aspects can also be edited with a workspace (within the Workspace tab) and, in order to it the aspect's value, you must type a Smalltalk expression and choose Accept from the Workspace menu. Some more complicated aspects are only displayed in the right hand pane and in order to edit them you must double click the aspect entry to bring up a suitable dialog. Font and colour aspects are of this nature. Adding the fields We'll take you through the creation of one of the fields to get you used to the View Composer's operation. After that, you'll be left to your own devices to finish off the remaining fields. 1. Let's add an entry field for the account name. We know that the account name is being handled by a TextPresenter (see table above) so find the TextPresenter entry in the toolbox to see all the views that are appropriate for it. An account name is single line text and we can use a "Single line text" view to handle the display and editing of this data. file:///c /OADocs/16.htm (3 of 6) [6/2/2000 8:42:11 AM]

87 Drawing a View for PersonalAccountShell Drag this item from the toolbox and drop it within the shell being composed Tip: notice that as objects are added to the View Composer they are displayed in the view hierarchy at bottom left. Although the view we are creating is fairly simple you will find this hierarchy indispensable in more complex situations, allowing you to navigate around and see the structure of your composition much more easily. Position the new view within the shell by dragging with the left mouse button held down. Any view can be re-sized by dragging the small grabbers at the corners or in the centre of each edge. Notice that, within the View Composer there is always one view that is currently selected and this is indicated by a heavy hatched border around it. If the selected view can be re-sized then the grabbers will also appear. Tip: many of the operations within the View Composer can act on more than one selection. In these cases the first view that was selected will be treated as the primary selection and the remainder as secondary selections. The Match and Align commands within the Draw menu are examples of commands that act on multiple selections. This single line text field you've just added is to connect to the TextPresenter called "name" (and therefore to the #name aspect of the PersonalAccount model). Therefore, we must set the name of the field to match. Ensure the text field is selected and choose the name aspect. Then type "name" into the right hand pane of the inspector. Hit the Enter key to commit the change and you'll see the entry in the view hierarchy change to display what you've typed. Most of our fields will require a static label text. Go back to the toolbox and drag a "Static text" view into the shell. Select the text aspect and type a suitable label for the account name field, eg: "Account Name:". In this case you'll see the text appear in the field directly, as you type. Note that this static text item is not going to be connected to any presenter so we don't need to give it a connection name. This demonstrates the flexibility of allowing the views to be defined separately from the presenters since only items involved in the application functionality need to be actually part of the presenter. Consequently, a composite view can be embellished without affecting the complexity of the underlying application code. Now you can add the remaining fields for the other presenters; just remember to drag across an appropriate view from the toolbox (ie: one listed under the presenter's class) and name it to match the name we gave to the presenter in our #createcomponents method. If in doubt check with the table of presenter types and names given above. Adding static decoration You can add other static decoration to your view to improve its appearance. In the example, we have added a static GroupBox view to surround the basic account details. Most views that can be associated with presenters are found in the toolbox under the presenter's class. For some views, however, it makes no sense to ever associate them with a presenter (a group box is a case in point), and these can be found associated with the view's class (GroupBox). file:///c /OADocs/16.htm (4 of 6) [6/2/2000 8:42:11 AM]

88 Drawing a View for PersonalAccountShell Adding Command Push Buttons In order to send commands to the presenter we can add some push buttons to our view. Look for PushButtons in the toolbox and drag four plain Push buttons across. Change the aspects of these as tabulated below but be aware when editing the command aspect that you'll be editing in a workspace. This means that you need to commit the changes using Workspace/Accept or Ctrl+S. The text aspect is easier; you just type, and the text appears immediately in the button. "command" aspect #newtransaction #edittransaction #removetransaction #exit "text" aspect &New &Edit &Delete E&xit Menus and Toolbars More often, commands are initiated from menus and toolbars. The View Composer includes a Menu Composer to help with the creation of menu bars and context menus. This is accessible from within the Modify/Set Menu Bar or Modify/Set Context Menu pulldowns but it is beyond the scope of this tutorial to go into the details of menu building. You should find the Menu Composer fairly intuitive to use if you want to add, say, a Transaction menu to the menu bar of the shell. Such a menu could be used to send the same commands as the push buttons thus giving the user a choice of how to use the interface. Tip: Due to a varary of Windows" the menu bar does not appear for a shell view when editing in in the ViewComposer's arena. You can, however, test a menu bar that you've designed by choosing Tesr from the File menu or by pressing F5. Saving the View It is now time to save the created view as a resource and to test the functionality of the view-presenter pair. Choose File/Save as or press the Save button on the View Composer's toolbar. In the resultant dialog find the presenter's class that this view is to be associated with, ie: PersonalAccountShell, and select this. Then enter a name for the view resource. In this case we'll choose to call our new view "Default view" so that it will be identified up by the standard Presenter class>>defaultview method. Testing the User Interface for PersonalAccount We now have a complete MVP triad for a PersonalAccount. At this stage we can test the user interface to verify how it interacts with the PersonalAccount model. In a workspace window evaluate: PersonalAccountShell show. You should see the view you've designed appear, displaying the contents of a newly created PersonalAccount object. In this case the PersonalAccountShell presenter that you've created also creates and owns its PersonalAccount model (it was specified by the defaultmodel class method, remember). However, it's also possible to bring up a PersonalAccountShell on a model that is already in existence. If you still have the workspace variables that we created earlier, then b will be be holding a suitable personal account. Evaluate: PersonalAccountShell showon: b. You should be able to see and edit the original details you entered into this account. At the moment you will not be able to add any transactions to the account since we have not completed the command handling methods that do this. file:///c /OADocs/16.htm (5 of 6) [6/2/2000 8:42:11 AM]

89 Drawing a View for PersonalAccountShell Once you've closed the shell, either by pressing Exit or with the system menu close box, inspect the contents of b and you should see the changes you have made to the account object. Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/16.htm (6 of 6) [6/2/2000 8:42:11 AM]

90 PersonalAccountTransactionDialog: a Presenter for PersonalAccountTransaction Creating an Application PersonalAccountTransactionDialog: a Presenter for PersonalAccountTransaction We now want to create a presenter that handles modal editing of PersonalAccountTransaction instances. The abstract classes Dialog and ValueDialog are suitable superclasses for this kind of modal editing. Both provide the ability to buffer the edit changes until the dialog is confirmed, usually by pressing an OK button. Tip: choose to subclass from Dialog if the model you are editing is mutable, that is, you are expecting to change the contents of the object in place. Often, however, you will be dealing with an immutable object which should not be modified directly. In such cases create your new class beneath ValueDialog and the standard #value, #value: protocol will be used to fetch the initial value for editing and to set the resultant value back into the model. For our PersonalAccountTransactionDialog we'll choose to edit the contents of an existing instance, ie we'll subclass Dialog to do this. Dialog subclass: #PersonalAccountTransactionDialog instancevariablenames: 'datepresenter amountpresenter descriptionpresenter isdebitpresenter ' classvariablenames: '' pooldictionaries: '' Write the createcomponents method to create the sub-presenters that are needed to edit a transaction model and then the model: method that connects these to the various aspects of the transaction. createcomponents "Private - Create the presenters contained by the receiver" super createcomponents. datepresenter := self add: DatePresenter new name: 'date'. amountpresenter := self add: NumberPresenter new name: 'amount'. descriptionpresenter := self add: TextPresenter new name: 'description'. isdebitpresenter := self add: BooleanPresenter new name: 'isdebit'. model: anaspectbuffer "Set the model associated with the receiver." super model: anaspectbuffer. datepresenter model: (anaspectbuffer aspectvalue: #date). amountpresenter model: (anaspectbuffer aspectvalue: #amount). descriptionpresenter model: (anaspectbuffer aspectvalue: #description). isdebitpresenter model: (anaspectbuffer aspectvalue: #isdebit). Tip: note that the model being assigned here is not a direct instance of PersonalAccountTransaction as we might expect, but instead it is an instance of the class AspectBuffer. This is created automatically by the Dialog framework to wrap the true subject model so that changes to it are buffered until they are explicitly applied back. For the most part, the aspect buffer can be treated in much the same way as the true subject model would have been, especially when requesting ValueAspectAdaptors onto its various aspects using #aspectvalue:. Add the defaultmodel class method to indicate that this presenter should have an instance of PersonalAccountTransaction as its model by default. Once again, there is no need to override the defaultview method providing we ensure that the view is saved under the name "Default view". file:///c /OADocs/17.htm (1 of 2) [6/2/2000 8:42:20 AM]

91 PersonalAccountTransactionDialog: a Presenter for PersonalAccountTransaction defaultmodel "Answer a default model to be assigned to the receiver when it is initialized." ^PersonalAccountTransaction new This is all the code we need to write to implement the PersonalAccountTransactionDialog. However, we can now go back to PersonalAccountShell and add the missing methods for newtransaction and edittransaction. newtransaction "Prompt for a new transaction and add it to the receiver's model" newtransaction (newtransaction := PersonalAccountTransactionDialog showmodal) notnil iftrue: [ self model addtransaction: newtransaction. self selectedtransactionornil: newtransaction ] Notice that, here, we are relying on the PersonalAccountTransactionDialog creating and editing a default model (that specified by the defaultmodel class method). The resultant transaction object will be answered from showmodal if OK is pressed, otherwise nil will be answered if Cancel is pressed. edittransaction "Edit the selected transaction" transaction transaction := self selectedtransactionornil. transaction notnil iftrue: [ self model removetransaction: transaction. PersonalAccountTransactionDialog showmodalon: transaction. self model addtransaction: transaction. self selectedtransactionornil: transaction ] In this case we are editing an existing selected transaction. The transaction is removed temorarily from the account and a PersonalAccountTransactionDialog is created and shown with this as its model. The dialog displays a copy of the model and any changes made are only written back to it if the dialog is confirmed. Otherwise, the original transaction object is left untouched. The resultant transaction is then added back into the account which causes the account balance to be updated appropriately. Tip: there are a number of instance creation methods in the Presenter class that help you create presenters in a variety of different ways. You should review these to know what's available; look at the class methods of Presenter in the "instance creation" category. Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/17.htm (2 of 2) [6/2/2000 8:42:20 AM]

92 Drawing a View for PersonalAccountTransactionDialog Creating an Application Drawing a View for PersonalAccountTransactionDialog Following basically the same procedure as before, use the View Composer to create a view for the PersonalAccountTransactionDialog presenter. This time, however, you are creating a dialog, so you should close the shell view that the View Composer initially creates for you and then drag a dialog view across from the toolbox. Tip: you'll find a suitable dialog view under the Dialog class, labelled "Default view". Alternatively, you can use the File/New Dialog View command to create a blank dialog for painting on. You'll want to end up with something like this: Before you start, confirm the connection points to the presenter. In PersonalAccountTransactionDialog we have: Sub-presenter type Connection name Model aspect DatePresenter 'date' #date NumberPresenter 'amount' #amount TextPresenter 'description' #description BooleanPresenter 'isdebit' #isdebit Tip: you'll find that the DatePresenter class has two possible views that can be used to display dates. In the above we have chosen the Text view so that the date will be displayed and edited in a conventional text entry field. You might also like to try using a Date picker which is the Windows control specifically designed for the graphical display and entry of date information. The interesting thing here, is that you file:///c /OADocs/18.htm (1 of 2) [6/2/2000 8:42:29 AM]

93 Drawing a View for PersonalAccountTransactionDialog can choose either view (or maybe go back later and choose a different one) without having to change any of your Smalltalk (presenter) code. This again demonstates the real flexibility of MVP. Saving the View Save the created view as a resource called 'Default view' in the PersonalAccountTransactionDialog class. Testing the User Interface for PersonalAccountTransactionDialog We can now test the combination of a PersonalAccountShell and a PersonalAccountTransactionDialog working in tandem. In a workspace evaluate: PersonalAccountShell show. Enter some details for an account and then press the New button to create a new transaction on it. You should see the dialog that you've just created appear, editing a default instance of PersonalAccountTransaction. Fill in the details for the transaction and press OK to confirm the changes. An entry for the transaction will appear in the transaction list in the account details view. You can continue to add more transactions and watch the account balance diminish as each is entered. Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/18.htm (2 of 2) [6/2/2000 8:42:29 AM]

94 PersonalMoneyShell: a Presenter for PersonalMoney Creating an Application PersonalMoneyShell: a Presenter for PersonalMoney The final Presenter-View pair that we need to create will be the user interface for an instance of PersonalMoney which, in fact, is the entry point to the entire application. If you recall, it is the responsibility of a PersonalMoney instance to hold a list of all the accounts for a particular user. Each account, in turn, holds all the transactions on it. Therefore the PersonalMoney object contains a network of all the data related to a user's accounts. It would be convenient if this information could be saved to, and restored from, disk easily. Luckily, the Dolphin MVP framework provides an abstract class, DocumentShell, which implements much of the grunt work necessary for saving a model to disk and allowing it to be reloaded later. So, we'll create our presenter class PersonalMoneyShell as a subclass of DocumentShell. DocumentShell subclass: #PersonalMoneyShell instancevariablenames: 'ownerpresenter accountspresenter' classvariablenames: '' pooldictionaries: '' The createcomponents and model: methods are pretty straightforward, as before: createcomponents "Private - Create the presenters contained by the receiver" super createcomponents. ownerpresenter := self add: TextPresenter new name: 'owner'. accountspresenter := self add: ListPresenter new name: 'accounts'. model: apersonalmoney "Set the model associated with the receiver." super model: apersonalmoney. ownerpresenter model: (apersonalmoney aspectvalue: #owner). accountspresenter model: (apersonalmoney accounts). Remember to specify the defaultmodel class method: defaultmodel "Answer a default model to be assigned to the receiver when it is initialized." ^PersonalMoney new Add the accessors: selectedaccountornil "Answer the currently selected account or nil if there is none" ^accountspresenter selectionornil selectedaccountornil: apersonalaccountornil "Sets the currently selected account to apersonalaccountornil. If nil if there will be no selection" ^accountspresenter selectionornil: apersonalaccountornil hasselectedaccount "Answer true if there is a currently selected account in the receiver" file:///c /OADocs/19.htm (1 of 3) [6/2/2000 8:42:37 AM]

95 PersonalMoneyShell: a Presenter for PersonalMoney ^accountspresenter hasselection And now the command handlers, once again to be placed in the commands category: newaccount "Prompt for a new account and add it to the receiver's model" newaccount newaccount := self model addaccount: PersonalAccount new. self selectedaccountornil: newaccount. self editaccount removeaccount "Removes the current account from the receiver's model" self hasselectedaccount iftrue: [ self model removeaccount: self selectedaccountornil ] editaccount "Edit the selected account" ]. account index shell self hasselectedaccount iftrue: [ account := self selectedaccountornil. shell := PersonalAccountShell showon: account. shell when: #viewclosed send: #updateaccount: to: self with: account We tack on to the notification of #viewdestroyed here as an indication that the editing of a particular account has been completed. We can use this point to update the representation of the account in our accounts list. Tip: this is only necessary be because we chose to edit our accounts using a modeless shell window rather than a dialog. In the latter case we would implicitly know when the editing operation was complete (following the #showmodal call) and the update could be done at this time. However, using a shell is sometimes more user friendly than using a dialog, the price being some extra coding complexity. updateaccount: apersonalaccount "Update apersonalaccount in the accounts list" index index := self model accounts indexof: apersonalaccount. self model accounts updateatindex: index There are two additional class methods that can be overridden by subclasses of DocumentShell. These indicate what file extensions to use for the disk file representations of the model. defaultfileextension "Answer a default extension that will be used for files saved from the receiver" ^'pm' filetypes "Answer an Array of file types that can be associated with this class of document." ^#(('Personal Money files (*.pm)' '*.pm') ('All Files (*.*)' '*.*')) Tip: remember these are class methods. file:///c /OADocs/19.htm (2 of 3) [6/2/2000 8:42:37 AM]

96 PersonalMoneyShell: a Presenter for PersonalMoney Click here to move on to the next section or here to go back to the previous section. file:///c /OADocs/19.htm (3 of 3) [6/2/2000 8:42:37 AM]

97 Drawing a View for PersonalMoneyShell Creating an Application Drawing a View for PersonalMoneyShell Use the View Composer to draw the shell view for a PersonalMoneyShell. The connection points to the Presenter are as follows: Sub-presenter type Connection name Model aspect TextPresenter 'owner' #owner ListPresenter 'accounts' #accounts Also you must configure the command buttons appropriately: "command" aspect #newaccount #editaccount #removeaccount #exit "text" aspect &New &Edit &Delete E&xit In order to use the document save and load facilities you will have to add a File menu containing the commands: #fileopen, #filesave and #filesaveas. Use the Menu Composer accessible from Draw/Menu/MenuBar to do this. file:///c /OADocs/20.htm (1 of 3) [6/2/2000 8:42:46 AM]

98 Drawing a View for PersonalMoneyShell Saving the View Save the created view as a resource called 'Default view' in the PersonalMoneyShell class. Testing the PersonalMoney application To start the application, evaluate: PersonalMoneyShell show Enter your name in the owner field and then press the New button to add an account. You can enter transactions on this account as before. If you wish to save your account information choose File/Save and enter an appropriate name for the file (it will be given a.pm extension by default). Later you can reload this file using File/Open. The PersonalMoney application in use file:///c /OADocs/20.htm (2 of 3) [6/2/2000 8:42:46 AM]

99 Drawing a View for PersonalMoneyShell Click here to go back to the previous section. file:///c /OADocs/20.htm (3 of 3) [6/2/2000 8:42:46 AM]

CS2900 Introductory Programming with Python and C++ Kevin Squire LtCol Joel Young Fall 2007

CS2900 Introductory Programming with Python and C++ Kevin Squire LtCol Joel Young Fall 2007 CS2900 Introductory Programming with Python and C++ Kevin Squire LtCol Joel Young Fall 2007 Course Web Site http://www.nps.navy.mil/cs/facultypages/squire/cs2900 All course related materials will be posted

More information

6.001 Notes: Section 8.1

6.001 Notes: Section 8.1 6.001 Notes: Section 8.1 Slide 8.1.1 In this lecture we are going to introduce a new data type, specifically to deal with symbols. This may sound a bit odd, but if you step back, you may realize that everything

More information

6.001 Notes: Section 15.1

6.001 Notes: Section 15.1 6.001 Notes: Section 15.1 Slide 15.1.1 Our goal over the next few lectures is to build an interpreter, which in a very basic sense is the ultimate in programming, since doing so will allow us to define

More information

6.001 Notes: Section 6.1

6.001 Notes: Section 6.1 6.001 Notes: Section 6.1 Slide 6.1.1 When we first starting talking about Scheme expressions, you may recall we said that (almost) every Scheme expression had three components, a syntax (legal ways of

More information

The System Transcript, Class Point and Inspectors

The System Transcript, Class Point and Inspectors Module 4 1 Module 4: The System Transcript, Class Point and Inspectors This module starts by introducing the System Transcript, illustrating how it can be used with a number of examples. The Transcript

More information

BASIC COMPUTATION. public static void main(string [] args) Fundamentals of Computer Science I

BASIC COMPUTATION. public static void main(string [] args) Fundamentals of Computer Science I BASIC COMPUTATION x public static void main(string [] args) Fundamentals of Computer Science I Outline Using Eclipse Data Types Variables Primitive and Class Data Types Expressions Declaration Assignment

More information

printf( Please enter another number: ); scanf( %d, &num2);

printf( Please enter another number: ); scanf( %d, &num2); CIT 593 Intro to Computer Systems Lecture #13 (11/1/12) Now that we've looked at how an assembly language program runs on a computer, we're ready to move up a level and start working with more powerful

More information

VARIABLES. Aim Understanding how computer programs store values, and how they are accessed and used in computer programs.

VARIABLES. Aim Understanding how computer programs store values, and how they are accessed and used in computer programs. Lesson 2 VARIABLES Aim Understanding how computer programs store values, and how they are accessed and used in computer programs. WHAT ARE VARIABLES? When you input data (i.e. information) into a computer

More information

CS102: Variables and Expressions

CS102: Variables and Expressions CS102: Variables and Expressions The topic of variables is one of the most important in C or any other high-level programming language. We will start with a simple example: int x; printf("the value of

More information

Excel Basics Rice Digital Media Commons Guide Written for Microsoft Excel 2010 Windows Edition by Eric Miller

Excel Basics Rice Digital Media Commons Guide Written for Microsoft Excel 2010 Windows Edition by Eric Miller Excel Basics Rice Digital Media Commons Guide Written for Microsoft Excel 2010 Windows Edition by Eric Miller Table of Contents Introduction!... 1 Part 1: Entering Data!... 2 1.a: Typing!... 2 1.b: Editing

More information

TOPIC 2 INTRODUCTION TO JAVA AND DR JAVA

TOPIC 2 INTRODUCTION TO JAVA AND DR JAVA 1 TOPIC 2 INTRODUCTION TO JAVA AND DR JAVA Notes adapted from Introduction to Computing and Programming with Java: A Multimedia Approach by M. Guzdial and B. Ericson, and instructor materials prepared

More information

Full file at

Full file at Java Programming: From Problem Analysis to Program Design, 3 rd Edition 2-1 Chapter 2 Basic Elements of Java At a Glance Instructor s Manual Table of Contents Overview Objectives s Quick Quizzes Class

More information

BEGINNER PHP Table of Contents

BEGINNER PHP Table of Contents Table of Contents 4 5 6 7 8 9 0 Introduction Getting Setup Your first PHP webpage Working with text Talking to the user Comparison & If statements If & Else Cleaning up the game Remembering values Finishing

More information

Variables and Typing

Variables and Typing Variables and Typing Christopher M. Harden Contents 1 The basic workflow 2 2 Variables 3 2.1 Declaring a variable........................ 3 2.2 Assigning to a variable...................... 4 2.3 Other

More information

USER GUIDE MADCAP DOC-TO-HELP 5. Getting Started

USER GUIDE MADCAP DOC-TO-HELP 5. Getting Started USER GUIDE MADCAP DOC-TO-HELP 5 Getting Started Copyright 2018 MadCap Software. All rights reserved. Information in this document is subject to change without notice. The software described in this document

More information

SEER AKADEMI LINUX PROGRAMMING AND SCRIPTINGPERL 7

SEER AKADEMI LINUX PROGRAMMING AND SCRIPTINGPERL 7 SEER AKADEMI LINUX PROGRAMMING AND SCRIPTINGPERL 7 Hi everyone once again welcome to this lecture we are actually the course is Linux programming and scripting we have been talking about the Perl, Perl

More information

Introduction to the C++ Programming Language

Introduction to the C++ Programming Language LESSON SET 2 Introduction to the C++ Programming Language OBJECTIVES FOR STUDENT Lesson 2A: 1. To learn the basic components of a C++ program 2. To gain a basic knowledge of how memory is used in programming

More information

12/22/11. Java How to Program, 9/e. Help you get started with Eclipse and NetBeans integrated development environments.

12/22/11. Java How to Program, 9/e. Help you get started with Eclipse and NetBeans integrated development environments. Java How to Program, 9/e Education, Inc. All Rights Reserved. } Java application programming } Use tools from the JDK to compile and run programs. } Videos at www.deitel.com/books/jhtp9/ Help you get started

More information

Divisibility Rules and Their Explanations

Divisibility Rules and Their Explanations Divisibility Rules and Their Explanations Increase Your Number Sense These divisibility rules apply to determining the divisibility of a positive integer (1, 2, 3, ) by another positive integer or 0 (although

More information

MAXQDA and Chapter 9 Coding Schemes

MAXQDA and Chapter 9 Coding Schemes MAXQDA and Chapter 9 Coding Schemes Chapter 9 discusses how the structures of coding schemes, alternate groupings are key to moving forward with analysis. The nature and structures of the coding scheme

More information

First Java Program - Output to the Screen

First Java Program - Output to the Screen First Java Program - Output to the Screen These notes are written assuming that the reader has never programmed in Java, but has programmed in another language in the past. In any language, one of the

More information

This chapter is intended to take you through the basic steps of using the Visual Basic

This chapter is intended to take you through the basic steps of using the Visual Basic CHAPTER 1 The Basics This chapter is intended to take you through the basic steps of using the Visual Basic Editor window and writing a simple piece of VBA code. It will show you how to use the Visual

More information

Mobile Computing Professor Pushpendra Singh Indraprastha Institute of Information Technology Delhi Java Basics Lecture 02

Mobile Computing Professor Pushpendra Singh Indraprastha Institute of Information Technology Delhi Java Basics Lecture 02 Mobile Computing Professor Pushpendra Singh Indraprastha Institute of Information Technology Delhi Java Basics Lecture 02 Hello, in this lecture we will learn about some fundamentals concepts of java.

More information

TourMaker Reference Manual. Intro

TourMaker Reference Manual. Intro TourMaker Reference Manual Intro Getting Started Tutorial: Edit An Existing Tour Key Features & Tips Tutorial: Create A New Tour Posting A Tour Run Tours From Your Hard Drive Intro The World Wide Web is

More information

Compilation and Execution Simplifying Fractions. Loops If Statements. Variables Operations Using Functions Errors

Compilation and Execution Simplifying Fractions. Loops If Statements. Variables Operations Using Functions Errors First Program Compilation and Execution Simplifying Fractions Loops If Statements Variables Operations Using Functions Errors C++ programs consist of a series of instructions written in using the C++ syntax

More information

IT 374 C# and Applications/ IT695 C# Data Structures

IT 374 C# and Applications/ IT695 C# Data Structures IT 374 C# and Applications/ IT695 C# Data Structures Module 2.1: Introduction to C# App Programming Xianrong (Shawn) Zheng Spring 2017 1 Outline Introduction Creating a Simple App String Interpolation

More information

CPS122 Lecture: From Python to Java last revised January 4, Objectives:

CPS122 Lecture: From Python to Java last revised January 4, Objectives: Objectives: CPS122 Lecture: From Python to Java last revised January 4, 2017 1. To introduce the notion of a compiled language 2. To introduce the notions of data type and a statically typed language 3.

More information

Chapter 2. Designing a Program. Input, Processing, and Output Fall 2016, CSUS. Chapter 2.1

Chapter 2. Designing a Program. Input, Processing, and Output Fall 2016, CSUS. Chapter 2.1 Chapter 2 Input, Processing, and Output Fall 2016, CSUS Designing a Program Chapter 2.1 1 Algorithms They are the logic on how to do something how to compute the value of Pi how to delete a file how to

More information

A Quick Tour GETTING STARTED WHAT S IN THIS CHAPTER?

A Quick Tour GETTING STARTED WHAT S IN THIS CHAPTER? 1 A Quick Tour WHAT S IN THIS CHAPTER? Installing and getting started with Visual Studio 2012 Creating and running your fi rst application Debugging and deploying an application Ever since software has

More information

SPARK-PL: Introduction

SPARK-PL: Introduction Alexey Solovyev Abstract All basic elements of SPARK-PL are introduced. Table of Contents 1. Introduction to SPARK-PL... 1 2. Alphabet of SPARK-PL... 3 3. Types and variables... 3 4. SPARK-PL basic commands...

More information

(Refer Slide Time: 01:12)

(Refer Slide Time: 01:12) Internet Technology Prof. Indranil Sengupta Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur Lecture No #22 PERL Part II We continue with our discussion on the Perl

More information

Language Basics. /* The NUMBER GAME - User tries to guess a number between 1 and 10 */ /* Generate a random number between 1 and 10 */

Language Basics. /* The NUMBER GAME - User tries to guess a number between 1 and 10 */ /* Generate a random number between 1 and 10 */ Overview Language Basics This chapter describes the basic elements of Rexx. It discusses the simple components that make up the language. These include script structure, elements of the language, operators,

More information

Assoc. Prof. Dr. Marenglen Biba. (C) 2010 Pearson Education, Inc. All rights reserved.

Assoc. Prof. Dr. Marenglen Biba. (C) 2010 Pearson Education, Inc. All rights reserved. Assoc. Prof. Dr. Marenglen Biba (C) 2010 Pearson Education, Inc. All rights reserved. Java application A computer program that executes when you use the java command to launch the Java Virtual Machine

More information

6.001 Notes: Section 1.1

6.001 Notes: Section 1.1 6.001 Notes: Section 1.1 Slide 1.1.1 This first thing we need to do is discuss the focus of 6.001. What is this course all about? This seems quite obvious -- this is a course about computer science. But

More information

Variables and Literals

Variables and Literals C++ By 4 EXAMPLE Variables and Literals Garbage in, garbage out! To understand data processing with C++, you must understand how C++ creates, stores, and manipulates data. This chapter teaches you how

More information

Bits, Words, and Integers

Bits, Words, and Integers Computer Science 52 Bits, Words, and Integers Spring Semester, 2017 In this document, we look at how bits are organized into meaningful data. In particular, we will see the details of how integers are

More information

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur Lecture 04 Programs with IO and Loop We will now discuss the module 2,

More information

5/3/2006. Today! HelloWorld in BlueJ. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont.

5/3/2006. Today! HelloWorld in BlueJ. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont. Today! Build HelloWorld yourself in BlueJ and Eclipse. Look at all the Java keywords. Primitive Types. HelloWorld in BlueJ 1. Find BlueJ in the start menu, but start the Select VM program instead (you

More information

Math Modeling in Java: An S-I Compartment Model

Math Modeling in Java: An S-I Compartment Model 1 Math Modeling in Java: An S-I Compartment Model Basic Concepts What is a compartment model? A compartment model is one in which a population is modeled by treating its members as if they are separated

More information

Memory Addressing, Binary, and Hexadecimal Review

Memory Addressing, Binary, and Hexadecimal Review C++ By A EXAMPLE Memory Addressing, Binary, and Hexadecimal Review You do not have to understand the concepts in this appendix to become well-versed in C++. You can master C++, however, only if you spend

More information

COMP-202 Unit 2: Java Basics. CONTENTS: Using Expressions and Variables Types Strings Methods

COMP-202 Unit 2: Java Basics. CONTENTS: Using Expressions and Variables Types Strings Methods COMP-202 Unit 2: Java Basics CONTENTS: Using Expressions and Variables Types Strings Methods Assignment 1 Assignment 1 posted on WebCt and course website. It is due May 18th st at 23:30 Worth 6% Part programming,

More information

In our first lecture on sets and set theory, we introduced a bunch of new symbols and terminology.

In our first lecture on sets and set theory, we introduced a bunch of new symbols and terminology. Guide to and Hi everybody! In our first lecture on sets and set theory, we introduced a bunch of new symbols and terminology. This guide focuses on two of those symbols: and. These symbols represent concepts

More information

Expressions and Data Types CSC 121 Spring 2015 Howard Rosenthal

Expressions and Data Types CSC 121 Spring 2015 Howard Rosenthal Expressions and Data Types CSC 121 Spring 2015 Howard Rosenthal Lesson Goals Understand the basic constructs of a Java Program Understand how to use basic identifiers Understand simple Java data types

More information

Variables and Constants

Variables and Constants HOUR 3 Variables and Constants Programs need a way to store the data they use. Variables and constants offer various ways to work with numbers and other values. In this hour you learn: How to declare and

More information

Lecture 05 I/O statements Printf, Scanf Simple statements, Compound statements

Lecture 05 I/O statements Printf, Scanf Simple statements, Compound statements Programming, Data Structures and Algorithms Prof. Shankar Balachandran Department of Computer Science and Engineering Indian Institute of Technology, Madras Lecture 05 I/O statements Printf, Scanf Simple

More information

Preprocessor Directives

Preprocessor Directives C++ By 6 EXAMPLE Preprocessor Directives As you might recall from Chapter 2, What Is a Program?, the C++ compiler routes your programs through a preprocessor before it compiles them. The preprocessor can

More information

Module 10 Inheritance, Virtual Functions, and Polymorphism

Module 10 Inheritance, Virtual Functions, and Polymorphism Module 10 Inheritance, Virtual Functions, and Polymorphism Table of Contents CRITICAL SKILL 10.1: Inheritance Fundamentals... 2 CRITICAL SKILL 10.2: Base Class Access Control... 7 CRITICAL SKILL 10.3:

More information

Maciej Sobieraj. Lecture 1

Maciej Sobieraj. Lecture 1 Maciej Sobieraj Lecture 1 Outline 1. Introduction to computer programming 2. Advanced flow control and data aggregates Your first program First we need to define our expectations for the program. They

More information

XP: Backup Your Important Files for Safety

XP: Backup Your Important Files for Safety XP: Backup Your Important Files for Safety X 380 / 1 Protect Your Personal Files Against Accidental Loss with XP s Backup Wizard Your computer contains a great many important files, but when it comes to

More information

Arduino IDE Friday, 26 October 2018

Arduino IDE Friday, 26 October 2018 Arduino IDE Friday, 26 October 2018 12:38 PM Looking Under The Hood Of The Arduino IDE FIND THE ARDUINO IDE DOWNLOAD First, jump on the internet with your favorite browser, and navigate to www.arduino.cc.

More information

MITOCW watch?v=0jljzrnhwoi

MITOCW watch?v=0jljzrnhwoi MITOCW watch?v=0jljzrnhwoi The following content is provided under a Creative Commons license. Your support will help MIT OpenCourseWare continue to offer high quality educational resources for free. To

More information

(Refer Slide Time: 00:26)

(Refer Slide Time: 00:26) Programming, Data Structures and Algorithms Prof. Shankar Balachandran Department of Computer Science and Engineering Indian Institute Technology, Madras Module 07 Lecture 07 Contents Repetitive statements

More information

NetLogo Tutorial Series: Langton's Ant. Nicholas Bennett Grass Roots Consulting

NetLogo Tutorial Series: Langton's Ant. Nicholas Bennett Grass Roots Consulting NetLogo Tutorial Series: Langton's Ant Nicholas Bennett Grass Roots Consulting nickbenn@g-r-c.com July 2010 Copyright Copyright 2010, Nicholas Bennett. All rights reserved. NetLogo Tutorial Series: Langton's

More information

Introduction to Java Applications

Introduction to Java Applications 2 Introduction to Java Applications OBJECTIVES In this chapter you will learn: To write simple Java applications. To use input and output statements. Java s primitive types. Basic memory concepts. To use

More information

The Domino Designer QuickStart Tutorial

The Domino Designer QuickStart Tutorial The Domino Designer QuickStart Tutorial 1. Welcome The Domino Designer QuickStart Tutorial You've installed Domino Designer, you've taken the Designer Guided Tour, and maybe you've even read some of the

More information

Binary, Hexadecimal and Octal number system

Binary, Hexadecimal and Octal number system Binary, Hexadecimal and Octal number system Binary, hexadecimal, and octal refer to different number systems. The one that we typically use is called decimal. These number systems refer to the number of

More information

Slide 1 Side Effects Duration: 00:00:53 Advance mode: Auto

Slide 1 Side Effects Duration: 00:00:53 Advance mode: Auto Side Effects The 5 numeric operators don't modify their operands Consider this example: int sum = num1 + num2; num1 and num2 are unchanged after this The variable sum is changed This change is called a

More information

ArcView QuickStart Guide. Contents. The ArcView Screen. Elements of an ArcView Project. Creating an ArcView Project. Adding Themes to Views

ArcView QuickStart Guide. Contents. The ArcView Screen. Elements of an ArcView Project. Creating an ArcView Project. Adding Themes to Views ArcView QuickStart Guide Page 1 ArcView QuickStart Guide Contents The ArcView Screen Elements of an ArcView Project Creating an ArcView Project Adding Themes to Views Zoom and Pan Tools Querying Themes

More information

What did we talk about last time? Examples switch statements

What did we talk about last time? Examples switch statements Week 4 - Friday What did we talk about last time? Examples switch statements History of computers Hardware Software development Basic Java syntax Output with System.out.print() Mechanical Calculation

More information

Programming Fundamentals

Programming Fundamentals Programming Fundamentals Computers are really very dumb machines -- they only do what they are told to do. Most computers perform their operations on a very primitive level. The basic operations of a computer

More information

CPS122 Lecture: From Python to Java

CPS122 Lecture: From Python to Java Objectives: CPS122 Lecture: From Python to Java last revised January 7, 2013 1. To introduce the notion of a compiled language 2. To introduce the notions of data type and a statically typed language 3.

More information

REVIEW. The C++ Programming Language. CS 151 Review #2

REVIEW. The C++ Programming Language. CS 151 Review #2 REVIEW The C++ Programming Language Computer programming courses generally concentrate on program design that can be applied to any number of programming languages on the market. It is imperative, however,

More information

Getting Started with Web Services

Getting Started with Web Services Getting Started with Web Services Getting Started with Web Services A web service is a set of functions packaged into a single entity that is available to other systems on a network. The network can be

More information

Basics of Java Programming

Basics of Java Programming Basics of Java Programming Lecture 2 COP 3252 Summer 2017 May 16, 2017 Components of a Java Program statements - A statement is some action or sequence of actions, given as a command in code. A statement

More information

(Refer Slide Time: 00:51)

(Refer Slide Time: 00:51) Programming, Data Structures and Algorithms Prof. Shankar Balachandran Department of Computer Science and Engineering Indian Institute Technology, Madras Module 10 E Lecture 24 Content Example: factorial

More information

Slide 1 CS 170 Java Programming 1 Expressions Duration: 00:00:41 Advance mode: Auto

Slide 1 CS 170 Java Programming 1 Expressions Duration: 00:00:41 Advance mode: Auto CS 170 Java Programming 1 Expressions Slide 1 CS 170 Java Programming 1 Expressions Duration: 00:00:41 What is an expression? Expression Vocabulary Any combination of operators and operands which, when

More information

Getting started 7. Saving data 23

Getting started 7. Saving data 23 Contents 1 2 3 4 Getting started 7 Programming code 8 Setting up 10 Exploring IDLE 12 Getting help 14 Saving programs 16 Storing values 18 Adding comments 20 Naming rules 21 Summary 22 Saving data 23 Storing

More information

Inspiration Quick Start Tutorial

Inspiration Quick Start Tutorial Inspiration Quick Start Tutorial 1 Inspiration Quick Start Tutorial This tutorial is a great starting point for learning how to use Inspiration. Please plan on about 45 minutes from start to finish. If

More information

Interface. 2. Interface Adobe InDesign CS2 H O T

Interface. 2. Interface Adobe InDesign CS2 H O T 2. Interface Adobe InDesign CS2 H O T 2 Interface The Welcome Screen Interface Overview The Toolbox Toolbox Fly-Out Menus InDesign Palettes Collapsing and Grouping Palettes Moving and Resizing Docked or

More information

3 Getting Started with Objects

3 Getting Started with Objects 3 Getting Started with Objects If you are an experienced IDE user, you may be able to do this tutorial without having done the previous tutorial, Getting Started. However, at some point you should read

More information

CS106X Handout 03 Autumn 2012 September 24 th, 2012 Getting Started

CS106X Handout 03 Autumn 2012 September 24 th, 2012 Getting Started CS106X Handout 03 Autumn 2012 September 24 th, 2012 Getting Started Handout written by Julie Zelenski, Mehran Sahami, Robert Plummer, and Jerry Cain. After today s lecture, you should run home and read

More information

Getting Started (1.8.7) 9/2/2009

Getting Started (1.8.7) 9/2/2009 2 Getting Started For the examples in this section, Microsoft Windows and Java will be used. However, much of the information applies to other operating systems and supported languages for which you have

More information

Excerpt from: Stephen H. Unger, The Essence of Logic Circuits, Second Ed., Wiley, 1997

Excerpt from: Stephen H. Unger, The Essence of Logic Circuits, Second Ed., Wiley, 1997 Excerpt from: Stephen H. Unger, The Essence of Logic Circuits, Second Ed., Wiley, 1997 APPENDIX A.1 Number systems and codes Since ten-fingered humans are addicted to the decimal system, and since computers

More information

3 The L oop Control Structure

3 The L oop Control Structure 3 The L oop Control Structure Loops The while Loop Tips and Traps More Operators The for Loop Nesting of Loops Multiple Initialisations in the for Loop The Odd Loop The break Statement The continue Statement

More information

Exsys RuleBook Selector Tutorial. Copyright 2004 EXSYS Inc. All right reserved. Printed in the United States of America.

Exsys RuleBook Selector Tutorial. Copyright 2004 EXSYS Inc. All right reserved. Printed in the United States of America. Exsys RuleBook Selector Tutorial Copyright 2004 EXSYS Inc. All right reserved. Printed in the United States of America. This documentation, as well as the software described in it, is furnished under license

More information

In further discussion, the books make other kinds of distinction between high level languages:

In further discussion, the books make other kinds of distinction between high level languages: Max and Programming This essay looks at Max from the point of view of someone with a bit of experience in traditional computer programming. There are several questions that come up from time to time on

More information

Expressions and Data Types CSC 121 Fall 2015 Howard Rosenthal

Expressions and Data Types CSC 121 Fall 2015 Howard Rosenthal Expressions and Data Types CSC 121 Fall 2015 Howard Rosenthal Lesson Goals Understand the basic constructs of a Java Program Understand how to use basic identifiers Understand simple Java data types and

More information

2 Getting Started. Getting Started (v1.8.6) 3/5/2007

2 Getting Started. Getting Started (v1.8.6) 3/5/2007 2 Getting Started Java will be used in the examples in this section; however, the information applies to all supported languages for which you have installed a compiler (e.g., Ada, C, C++, Java) unless

More information

Objects and Types. COMS W1007 Introduction to Computer Science. Christopher Conway 29 May 2003

Objects and Types. COMS W1007 Introduction to Computer Science. Christopher Conway 29 May 2003 Objects and Types COMS W1007 Introduction to Computer Science Christopher Conway 29 May 2003 Java Programs A Java program contains at least one class definition. public class Hello { public static void

More information

A Java program contains at least one class definition.

A Java program contains at least one class definition. Java Programs Identifiers Objects and Types COMS W1007 Introduction to Computer Science Christopher Conway 29 May 2003 A Java program contains at least one class definition. public class Hello { public

More information

DDDA User Guide Version 1.5

DDDA User Guide Version 1.5 DDDA User Guide Version 1.5 email: DDDASupport@thinksrs.com Copyright 2002 Stanford Research Systems, Inc. All Rights Reserved. Table Of Contents CHAPTER 1 DDDA... 3 INTRODUCTION... 3 REGISTERING YOUR

More information

Hello, and welcome to another episode of. Getting the Most Out of IBM U2. This is Kenny Brunel, and

Hello, and welcome to another episode of. Getting the Most Out of IBM U2. This is Kenny Brunel, and Hello, and welcome to another episode of Getting the Most Out of IBM U2. This is Kenny Brunel, and I'm your host for today's episode which introduces wintegrate version 6.1. First of all, I've got a guest

More information

CS02b Project 2 String compression with Huffman trees

CS02b Project 2 String compression with Huffman trees PROJECT OVERVIEW CS02b Project 2 String compression with Huffman trees We've discussed how characters can be encoded into bits for storage in a computer. ASCII (7 8 bits per character) and Unicode (16+

More information

Lutheran High North Technology The Finder

Lutheran High North Technology  The Finder Lutheran High North Technology shanarussell@lutheranhighnorth.org www.lutheranhighnorth.org/technology The Finder Your Mac s filing system is called the finder. In this document, we will explore different

More information

Here is a complete outline of the entire course as it is currently planned (contents approximate):

Here is a complete outline of the entire course as it is currently planned (contents approximate): Getting Started With The CHT Web Group Server A User s Guide INSTALLATION Installing this CHT Web Group Server software is your first step into the future of desktop web serving. Although the Web Group

More information

CS112 Lecture: Variables, Expressions, Computation, Constants, Numeric Input-Output

CS112 Lecture: Variables, Expressions, Computation, Constants, Numeric Input-Output CS112 Lecture: Variables, Expressions, Computation, Constants, Numeric Input-Output Last revised January 12, 2006 Objectives: 1. To introduce arithmetic operators and expressions 2. To introduce variables

More information

The Java Language Rules And Tools 3

The Java Language Rules And Tools 3 The Java Language Rules And Tools 3 Course Map This module presents the language and syntax rules of the Java programming language. You will learn more about the structure of the Java program, how to insert

More information

1. Let n be a positive number. a. When we divide a decimal number, n, by 10, how are the numeral and the quotient related?

1. Let n be a positive number. a. When we divide a decimal number, n, by 10, how are the numeral and the quotient related? Black Converting between Fractions and Decimals Unit Number Patterns and Fractions. Let n be a positive number. When we divide a decimal number, n, by 0, how are the numeral and the quotient related?.

More information

Pace University. Fundamental Concepts of CS121 1

Pace University. Fundamental Concepts of CS121 1 Pace University Fundamental Concepts of CS121 1 Dr. Lixin Tao http://csis.pace.edu/~lixin Computer Science Department Pace University October 12, 2005 This document complements my tutorial Introduction

More information

A lot of people make repeated mistakes of not calling their functions and getting errors. Make sure you're calling your functions.

A lot of people make repeated mistakes of not calling their functions and getting errors. Make sure you're calling your functions. Handout 2 Functions, Lists, For Loops and Tuples [ ] Functions -- parameters/arguments, "calling" functions, return values, etc. Please make sure you understand this example: def square(x): return x *

More information

A Tutorial on using Code::Blocks with Catalina 3.0.3

A Tutorial on using Code::Blocks with Catalina 3.0.3 A Tutorial on using Code::Blocks with Catalina 3.0.3 BASIC CONCEPTS...2 PREREQUISITES...2 INSTALLING AND CONFIGURING CODE::BLOCKS...3 STEP 1 EXTRACT THE COMPONENTS...3 STEP 2 INSTALL CODE::BLOCKS...3 Windows

More information

Tutorial 3: Using the Waveform Viewer Introduces the basics of using the waveform viewer. Read Tutorial SIMPLIS Tutorials SIMPLIS provide a range of t

Tutorial 3: Using the Waveform Viewer Introduces the basics of using the waveform viewer. Read Tutorial SIMPLIS Tutorials SIMPLIS provide a range of t Tutorials Introductory Tutorials These tutorials are designed to give new users a basic understanding of how to use SIMetrix and SIMetrix/SIMPLIS. Tutorial 1: Getting Started Guides you through getting

More information

The Definitive Guide to Fractal Awesomeness with J-WildFire!

The Definitive Guide to Fractal Awesomeness with J-WildFire! Installing Java and J-WildFire - by Martin Flink Copyright 2013 Martin Flink All Rights Reserved. No part of this document may be reproduced in any form without permission in writing from the author. Contact:

More information

Programming for the Web with PHP

Programming for the Web with PHP Aptech Ltd Version 1.0 Page 1 of 11 Table of Contents Aptech Ltd Version 1.0 Page 2 of 11 Abstraction Anonymous Class Apache Arithmetic Operators Array Array Identifier arsort Function Assignment Operators

More information

Variables, expressions and statements

Variables, expressions and statements Variables, expressions and statements 2.1. Values and data types A value is one of the fundamental things like a letter or a number that a program manipulates. The values we have seen so far are 2 (the

More information

With IBM BPM 8.5.5, the features needed to express both BPM solutions and case management oriented solutions comes together in one offering.

With IBM BPM 8.5.5, the features needed to express both BPM solutions and case management oriented solutions comes together in one offering. Case Management With the release of IBM BPM 8.5.5, case management capabilities were added to the product. It must be noted that these functions are only available with IBM BPM Advanced and the Basic Case

More information

CMPT 125: Lecture 3 Data and Expressions

CMPT 125: Lecture 3 Data and Expressions CMPT 125: Lecture 3 Data and Expressions Tamara Smyth, tamaras@cs.sfu.ca School of Computing Science, Simon Fraser University January 3, 2009 1 Character Strings A character string is an object in Java,

More information

\n is used in a string to indicate the newline character. An expression produces data. The simplest expression

\n is used in a string to indicate the newline character. An expression produces data. The simplest expression Chapter 1 Summary Comments are indicated by a hash sign # (also known as the pound or number sign). Text to the right of the hash sign is ignored. (But, hash loses its special meaning if it is part of

More information

Intro To Excel Spreadsheet for use in Introductory Sciences

Intro To Excel Spreadsheet for use in Introductory Sciences INTRO TO EXCEL SPREADSHEET (World Population) Objectives: Become familiar with the Excel spreadsheet environment. (Parts 1-5) Learn to create and save a worksheet. (Part 1) Perform simple calculations,

More information

Lesson 3 Transcript: Part 1 of 2 - Tools & Scripting

Lesson 3 Transcript: Part 1 of 2 - Tools & Scripting Lesson 3 Transcript: Part 1 of 2 - Tools & Scripting Slide 1: Cover Welcome to lesson 3 of the db2 on Campus lecture series. Today we're going to talk about tools and scripting, and this is part 1 of 2

More information