As we've already observed, every single class in the system ultimately inherits from object. This means that every single object in the system (instances and classes) will understand and respond to the messages (or protocol) defined in Obj ect. Here are some of the things it can do, discussed in the order in which you'll find them in the various protocols of Object:
In the initial ize-release protocol, the release method releases all the dependents (see Chapter 8—The Dependency Mechanism) that an object might have before it is destroyed. Notice that there is no initialize method defined in Object. This means that if you send initialize to an object which does not define this method somewhere else in its class hierarchy, you will get an error.
In accessing there are many methods which provide the foundations for subclasses which store data as collections. The only method in this protocol that you might want to use directly is yourself. This method, which just returns self, might at first seem rather pointless. However, there are certain rare circumstances in which it is useful. Browse the senders of yourself (using the senders command in a browser) to see some examples.
In testing, the class Object defines a whole load of things which its instances are not (nil, integer, string and so on). This is so that these messages can be over-ridden in the appropriate subclasses to return true instead of false.
In comparing we can see the definitions of two very important
comparisons in Smalltalk: = and ==. It is crucial to understand the difference between these two comparisons. The operator = tests whether two objects are 'equal'. This depends on the class of the object, and if you browse the implementors of = you will find that lots of
Chapter 6
classes redefine it in appropriate ways (for example, two Rectangle instances might be = if their coordinates are the same).
The operator == on the other hand, tests whether the receiver of the message and the parameter are 'equivalent'. This means whether they are two references to the same object. For example, the expression rect 1 == rect2 would only return true if recti and rect2 were two variables containing the same Rectangle instance, and not just if they contained two rectangles with the same coordinates. This is a much stronger test than =.
The comparing protocol also contains methods for hash-coding the object. These are used to provide efficient look up of objects when they are stored in certain kinds of collection.
The copying protocol contains methods for producing copies of objects. Smalltalk used to distinguish between a deepCopy (the object and all its instance variables were copied recursively), and a shallowCopy (the object was copied, but all the copy's instance variables pointed to the same objects as the original). However, deepCopy was found to be a fundamentally flawed concept, so now only shallowCopy is supported.
The converting protocol includes two methods (- > and asValue) for making other objects which contain the receiver as one of their instance variables. These just happen to be so frequently needed that they are included here for convenience.
The protocols dependents access , updating, changing and dependents collection are the protocols which contain the methods used to implement the dependency mechanism we'll look at in chapter 8. These methods are described in detail there.
The protocol printing contains methods which enable every object in the system to have the printed representation we mentioned earlier. You may have noticed that when you print an object using the development environment, it always describes itself in some useful way (for example aPopUpMenu) instead of giving you a useless internal pointer (like 7af41d25). The method responsible for this is called printOn: and it is called whenever the system needs the printed representation of an object. The default definition in Object simply uses the name of the object's class, prefixed with 'a' or 'an'. Many subclasses of Object redefine printOn: to generate much more useful strings which actually describe the individual object (for example a Point with x-coordinate 3 and y-coordinate 4 would print as 3@4, instead of just aPoint). If you want your objects to print more descriptively, you can also redefine printOn: in your class. Look at any of the other implementors of it to see examples.
The Smalltalk Class Library The printing protocol also contains the method storeString. This method generates a sequence of characters which form a piece of Smalltalk code. When executed this code will create an object exactly like the object to which the storeString message was sent. This remarkable facility is the basis of representing objects in serial form.
The next protocol, class membership, provides a set of facilities for testing which class an object is an instance of. Notice especially the difference between isMemberOf : (is an instance of a particular class) and isKindOf : (is an instance of a particular class or one of its subclasses).
The message handling protocol contains some important methods of which perform: is the simplest. We'll be looking at these methods in chapter 10—Pluggability and Adaptors.
The protocol error handling includes some useful methods like halt. When evaluated this stops execution of the current method and opens a notifier window. This means you can insert breakpoints in your code for debugging reasons simply by putting in the expression
self halt. The protocol also includes doesMofcunderstand: . This
message is sent to an object which does not understand a message it is supposed to be executing. Normally, it opens a notifier window, but you can over-ride it to do clever things if you wish.
Finally in this protocol, s h o u l d K E o t Z m p l e m e n t and subclassResponsibility are messages you can use to indicate that a subclass wants to 'undefine' a method defined in a superclass (preventing it being sent by raising an error if it is), or indicate that a subclass must implement a method which is defined in a superclass.
The user interface protocol provides methods that allow you to inspect any object, or browse its class. Just sending inspect or browse to any object will open the appropriate tool.
The remaining protocols in Object contain methods which are used internally and are unlikely to be of direct use to programmers. However, feel free to browse them if you want to understand more about how the system works.