Object Creation and Message Syntax Chapter 3 Contents

"Instantiation", or the instantiation of a class, is used in this manual to mean the creation of an object instance without regard to how that creation is achieved. For instantiation to occur the instance must be associated with a class, must be sized if the class is indexed, and must be named unless created at runtime as dynamic and nameless. Objects range in complexity from simple BYTEs and INTs through the "toolbox objects" such as windows and views that participate in Mac Toolbox operations. Mops provides several language elements designed to cope with this range of complexity in an economical way.

Message syntax is very uniform unless you need to explicity control the binding of a message, that is, the association of a message with a specific method definition. In the simple case no uncertainty about the receiver’s class exists and the binding occurs at compile time (early binding), but in other cases it must be achieved at runtime (late binding). The choice between the two, and the attendant tradeoffs, is dictated by overall program design as discussed in the following chapter, "More About Objects". Complete syntax for early-bound messages is given below, and some differences are commented on.

Object Declarations vs. Creation Methods

Declaration Instantiation
All compiled - as opposed to dynamic - objects require only a simple declaration for their instantiation. Typically, the predefined classes described as basic data structures, as well as the string, file, floating-point, and vector objects are instantiated in this way. (See below for toolbox classes.) A declared class instance is implicity created as a compiled object in the dictionary unless qualified as TEMP. The form of the declaration is simply

[array-size] class-name instance-name

(Brackets indicate optionality.) As can be seen, the declarations for scalar and array classes differ only in the array-size value that specifies the number of indexed elements the object is to have. Some examples are:

	Var		MAXTEMP
	Uint		MASK_1
	Handle		BUFFER4
32	wArray		GAME_STATE
6	X-Array		IOERR_VECTS
	HandleList	HEAP_OBJS
	String+		LOGDATA
	File		INITIALVALS
	Float		BIGNUMB
16	fArray		BIGNUMBS
	SWord_vector	VECTORVALUE

NOTE: Though constant and value definitions look much like array-object declarations, they are not objects but simply primitive data items, i.e., Mops words. (Unlike the analogous objects they cannot participate in complex objects as either ivars or array elements.)

The event-related classes Event and Mouse would be instantiated as above but are seldom if ever subclassed as it is very unlikely that the need to do so would arise.

Special-case TEMP Declarations
The TEMP{ ... } declaration "envelops", or takes a list of data-object declarations and declares them to be temporary within the scope of a word definition or a local section (see Part 3 - Miscellaneous Topics). Its effect within a definition is to make the objects local in scope as well as temporary. An additional effect is to allow an elementary data object to be instantiated in a register, or in a vector register if a Vector object.
Otherwise the objects declared as TEMP are created in a memory area on the return stack. The TEMP declaration syntax is

TEMP{ [ REGISTER ] obj-declaration [ [ REGISTER ] obj-declaration ... ] }

The optional form TEMP { ... } (with white space characters after the TEMP) is equivalent to TEMP{ ... } . A syntax example:

Temp{			Var          AVARIABLE
	register	Uint         AUINTEGER
	9		bArray       ABARRAY
	register	Float        AFPVARIABLE
	register	Word_vector  AVECTVARIABLE
}

Creation-Method Instantiation
Nameless dynamic objects, that is, heap-based objects of variable lifetime, are accessed either individually by a handle or by index into a collection of such objects (mediated by implicit handles). You declare either an ObjHandle or HandleList object and then send the appropriate object-creation message to either. The name of the creation method in either case is NEWOBJ: and the class of the desired instance is passed on the stack (as an xt). Examples:

Note that the deferred tick of the class name gives the method the needed class information, and that in the case of a handleList the newObj: message may appear within a DO loop that instantiates some required number of same-class instances.

(1)	objHandle   SHORTLIFE_OBJ		\ Declaration of handle for object
	['] Fugit  newObj: SHORTLIFE_OBJ	\ Creation of Fugit-subclass 
						\ instance


(2)	handleList   BUNCH_OF_OBJS		\ Declaration of a list of implicit
						\ handles

	['] Lotsa  newObj: BUNCH_OF_OBJS 	\ Creation of one object with 
						\ implicit handle
            . . .
	['] Lotsa  newObj: BUNCH_OF_OBJS 	\ Creation of another object in the 
						\ same list.
            . . .
	['] Oddball newObj:  BUNCH_OF_OBJS	\ Creation of an object of a 
						\ differing class

The Mops Toolbox Classes
Many interactions with the Mac Toolbox are quite complex and so are the Mops predefined classes and corresponding objects that deal with them. This is particularly true of objects of the classes (or subclasses) that facilitate windowing, e.g., WINDOW, WINDOW+, and VIEW plus a few others (Chapters 5, 6, and 9 of Part III). Window objects specifically might be said to lead two lives in that, while they are normal Mops object in most respects, some portion of their data area is shared between Mops and the toolbox. (Also, much of the object’s behavior is transparent to the user, which is after all the purpose of the toolbox classes, to hide lower-level detail of toolbox interactions.) Except for View they all have one or more methods that result in a toolbox call.

Like other objects a toolbox-class object can be created at compile time by declaration, as is shown in most examples. When necessary one or more or more can also be created dynamically using either of the newObj: messages discussed above. The one thing that is different about most classes of toolbox object is that they must be sent a NEW: or GETNEW: message to become effective. While these mesages may superficially look like object-creation messages they are not but serve to make the existent object known to, or "alive in", the Mac toolbox.

Much of the necessary NEW: messaging is performed by Mops automatically and transparently via the class hierarchy. To take a common example, when the user's code sends a NEW: to an object of class Window+ (or user-declared subclass thereof), the receiveršs default action is to "call" NEW: on its contained view which in turn does the same on any child views, and so on down the line. (Similar default behavior is defined for other messages as well, such as DRAW:) Thus, not only is the user insulated from system calls and all the attendant details, but also much inter-object messaging is made as transparent as possible.

Message Syntax
The basic form of a message to an object is:

[ stack-item ... ] selector [ object-name | objPtr-name | SELF | SUPER ]

where:

Although the syntax diagram above may look complex, it results in just a few simple forms. All messages conforming to that syntax are subject to early binding, i.e., complete resolution at compile time, the standard for Mops objects and messages. Some examples are:

" A Window Title"  new:     MyWind2
         elemIdx   at:      stateArray
                   update:  theScreen
         winMsg    Writer:  self
                   clear:   self
                   moved:   super						
                   where:   theMouse

Sometimes late binding is necessary, however, typically for dynamic objects or program-design reasons as described in the next chapter. In this case square brackets, i.e., [ ], usually appear in the message surrounding the identity of the receiver, which might be given by a runtime expression. Also, the receiver may be given by an object handle. Forms such as "selector **" and "selector []" are possible, as well as "selector [SELF]"

The possible forms of late-bound messages are described in detail in the "Early Vs. Late Binding" section of the following chapter.

Advanced Message Syntax
RightArrow

Have you ever listened to a Forth programmer's first reactions to using object extensions? A typical reaction is "Gee, having to send a message to an object sure seems like a lot more work than plain Forth". And in a sense they are right. But of course there are many advantages to object programming that far outweigh any extra (perceived or real) effort in writing object code.

A common initial complaint is that obtaining the value of an object or an ivar is cumbersome compared to what we can do with, for example, a VALUE or a local variable, or plain variable. Consider the following code using VAR, INT, or similar ivars (1):

get: x1 get: y1 get: x2 1- get: y2 put: temprect \ seems like a lot of get:s

With local variables or values we can write cleaner looking code (2):

x1 y1 x2 1- y2 put: temprect

RightArrow is a shortcut way of sending a get: or a put: message to an object, ivar, or any valid message receptor in Mops. The RightArrow is a single-character "arrow" pointing to the right, →. It is similar in appearance to the Smalltalk arrow, but it has a different meaning in Mops.

In order to properly see the RightArrow, the folder "MopsFont folder" must be installed. In OSX place the folder "MopsFont folder" in your Username:Library:Fonts folder. In OS9, if you use it, place all of the "files" from the "MopsFont folder" in your System 9 "Fonts" folder.

Then the RightArrow can be typed by either pressing 'option >' or simply pressing the "help" key on your keyboard.

An arrow appended to an object name, no space between object name and arrow, (or any message receptor) such as myIvar→ is functionally identical to get: myIvar. An arrow prefixed to an object name, no space between object name and arrow, (or any message receptor) such as →myIvar is functionally identical to put: myIvar. In fact the Mops interpreter / compiler has been modified to interpret myIvar→ as get: myIvar and ;→myIvar as put: myIvar.

So the above code, written for objects or ivars or other message recptors can now be written as follows (3):

x1→ y1→ x2→ 1- y2→ put: temprect \ much cleaner than 1) above

or even, at the programmer's discretion, as follows (4):

x1→ y1→ x2→ 1- y2→ →temprect

It's not that we don't like the get: and put: messages. We do like them. In fact the RightArrow syntax cannot work without them. But we also think the shorthand syntax will be appealing to many.

Side benefits to using the RightArrow include less typing and shorter source code.

A final note. Since the RightArrow character is non-standard (not ascii and not even standard Macintosh), in other fonts it will appear as a '>' with an underline, like '≥'. This is also the way it will appear in other Macintosh text or word processors that do not support the MopsFont font. But that's OK because that character is rarely used (at least in Mops programs that we've seen) and it is very similar in appearance to the RightArrow.

Cascaded Messages

Smalltalk uses cascaded messages and we decided that they could be useful in Mops as well. Consider the following snippet of code:

10 10 40 40 put: myrectangle  1 1 inset: myrectangle
draw: myrectangle  invert: myrectangle  clear: myrectangle

Cascaded messages let us rewrite the above as follows:

10 10 40 40 put: myrectangle 1 1 inset: | draw: | invert: | clear: |

The '|' (vertical bar), will cause the reference to the last object in the input stream to be reused. Note how this syntax once again allows for cleaner, shorter source code in the appropriate circumstances. Also again, the syntax is optional so you can use it where you like or not at all. It is especially useful when sending many messages to the same object (or ivar, etc.) at the same time. It is especially helpful if the object has a long name. We think many will appreciate this.

 

Previous Chapter Contents Next Chapter
This page online:  http://PowerMops.com/MopsManual/Reference/Chapter3.html