next up previous contents
Next: Object Precedence Lists Up: Class Hierarchies and Previous: Class Hierarchies and

The Introduction of super

 

Classes can be arranged in a tree structure by introducing a designated state variable, which specifies the superclass of the class being defined.

 

(define (class-name)
(let ((super (new-part super-class))
(self nil))
(let ((instance-variable init-value)
...)

(define (method formal-parameter...)
method-body)
...

(define (dispatch message)
(cond ((eqv? message selector) method)
...
(else (method-lookup super message))))

(set! self dispatch))

self))

Compared with the class pattern shown in section gif, the variables super and self are new. Super and self

correspond roughly to the Smalltalk [5] pseudo variables of the same names. (In section gif I will change the interpretation of self such that self and super

play the same role as in Smalltalk.)

Before I explain the remaining new elements of the class pattern from above I will introduce some terminology. If a class C has a superclass S, an object which is an instance of C is said to have an S object part (or just an S part.) Sometimes I will talk about an S object part as the super part of a C object.

  
Figure: The internal organization of an object with three parts.

Using this terminology, an instance of a class with a super class consists of a sequence of object parts.gif Figure gif shows an object with two super parts, together with the super and self variables at the three levels. Self refers to the procedure dispatch , which corresponds to self from chapter gif. Super refers to the ``higher level part'', which is allocated of the primitive new-part .

The procedure new-part is identical to the procedure new-instance , as defined in section gif.

 

(define (new-part class)
  (class))

Later in the report it turns out to be convenient to be able to distinguish the instantiation of whole classes from the instantiation of parts of classes.

The procedure method-lookup returns the method with a given selector in an object.

 

(define (method-lookup object selector)
  (cond ((procedure? object) (object selector))
         (else (error "Inappropriate object in method-lookup: " object))))

Given that dispatch in each class propagates unknow messages to its superclass (if any), method-lookup searches from the most specific to the most general class for a method with the given selector.

Let me illustrate in some more details what happens when a class with a super class is instantiated. Externally, an instance of a class is created as explained in section gif. Internally, the instantiation may start a chain of instantiations of parts, which stops when a root of the class hierarchy is reached (see below). As already explained, and as illustrated in figure gif, each part of the object contains a reference to the level above in the object-hierarchy.

Similarly, let me explain what happens during message passing when classes are organized in hierarchies. If a message message is sent to an object, and if the message ``falls through'' the cond -construct in dispatch , the form

(method-lookup super message)

is executed. Super is a reference to the superpart of the object. Eventually, the method whose selector matches the message is located, or the root of the class hierarchy is reached without finding a method with the given selector. In the former case the method is activated with actual parameters supplied in the send form. In the latter case, we want to get a error message, which signals that there are no methods that match the message.

To accommodate the behavior just described, the root of the class hierarchy may be defined in the following simple way:gif

 

(define (object)
  (let ((super ())
        (self nil))

   (define (dispatch message)
       ())
 
   (set! self dispatch)
   self))

This defines a trivial class, in which super is bound to the empty list, and with an empty dispatch procedure. Given this definition of the root of the hierarchy, the send

primitive from the previous section can be modified to react properly in the case that a message is unknown to an object:

 

(define (send object message . args)
  (let ((method (method-lookup object message)))
    (cond ((procedure? method) (apply method args))
          ((null? method) (error "Message not understood: " message))
          (else (error "Inappropriate result of method lookup: " method)))))

Compared with the version of send in section gif, this version handles the case where the method lookup does not return a method (signaled with the empty list, which is supposed to be returned from dispatch of the root class.) Notice that this version of send uses method-lookup , which was defined above.



next up previous contents
Next: Object Precedence Lists Up: Class Hierarchies and Previous: Class Hierarchies and



Kurt Noermark
Wed Mar 6 10:30:05 MET 1996