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

Another Interpretation of self

 

In the framework explained in section gif, self refers to that part of an object, in which it textually is contained.

  
Figure: Two different interpretations of self .

Figure gif(a) shows an object with three parts, and it is illustrated to which part of the object self refers.

Figure gif(b) shows an alternative way of interpreting self . Following this approach, self always refers to the object part, which corresponds to the most specialized class involved. This is the way self is used in Smalltalk-80 [5]. In Simula terms [4], this makes all methods virtual-like. I will now show how the situation in figure gif(b) can be obtained.

First, I will assume that each class definition contains an operation set-self , and that the message set-self! activates that operation.

 

(define (set-self object-part)
    (set! self object-part)
    (send super 'set-self! object-part))

Set-self assigns a new value to self , and it propagates a similar request to its super class. In object , which is assumed to be the root of the class hierarchy, no propagation should take place. I.e., (send super ...) should not be included in the set-self method of the class object .

A call to the procedure virtual-operations defined as

 

(define (virtual-operations object)
  (send object 'set-self! object))

declares that self in the object parameter, and in its (direct and indirect) superparts, follow the new interpretation.

The decision about the role of self can be postponed until class instantiation time. If we want the new interpretation, the primitive new-instance from section gif should be changed to the following procedure:gif

 

(define (new-instance class)
 (let ((instance (class)))
   (virtual-operations instance)
   instance))

Notice that we don't want to change new-part in a similar way, because this would result in a bunch of temporary assignments of self

to gradually larger and larger parts of the object under construction.

There are other ways to obtain the Smalltalk-like interpretation of self . In [2] it is proposed that self of the outer part of the object is passed as a parameter to each method. In that way the methods that I call set-self are not necessary, but in return each method of every class must take an extra parameter.

As the conclusion of this section, let me illustrate how one can take advantage of the new interpretation of self . I want to implement a method responds-to , which tells whether a given object responds to a given message. Because every object should have access to this method, it is natural to place it in the root class. The method is here shown in context of the whole object class (which is an extension of the trivial object class shown in section gif.)

   

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

   (define (set-self obj-part)
     (set! self obj-part))

   (define (responds-to message)
     (let ((method (method-lookup self message)))
       (if method #t #f)))

   (define (dispatch message)
     (cond ((eqv? message 'set-self!) set-self)
           ((eqv? message 'responds-to?) responds-to)
           (else ())))
 
   (set! self dispatch)
   self))

The operation responds-to relies on the fact that self

in object refers to the ``top part'' of the object, of which it is a part. (Method-lookup self message) searches through an object from the most specific part towards the more general parts. If an operation is found, which responds to message , it is returned from method-lookup . If not, the search reaches the dispatch procedure in the class object , which returns the empty list.

It can be concluded that method lookup, as known from, e.g., Smalltalk, is easy to simulate in our framework via a change of the interpretation of self .



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



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