next up previous contents
Next: The most General Up: Metaclasses Previous: Metaclasses

The pattern of Metaclasses

 

In this section I will show and discuss the syntactic pattern, which is used to simulate metaclasses. For simplicity, I assume that only single inheritance is involved. More specifically, this chapter will be based on the framework from section gif.

A metaclass can be simulated using the following pattern:gif

 

(define (metaclass-name)
(let ((self nil)
(super (new-part super-metaclass)))

;; class variables and methods
(let ((class-variable init-value)
...)

(define (class-method formal-parameters...)
body)
...

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

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

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

(set! self inner-dispatch))
self))

(define (outer-dispatch m)
(cond ((eqv? m 'instantiator) instance-description)
((eqv? m selector) method)
...
(else (method-lookup super m))))

(set! self outer-dispatch))
self))

Although this class pattern is slightly more complicated than the similar patterns from the previous chapters, the overall structure of it is quite simple. Figure gif illustrates the main components of the class template from above.

  
Figure: The main components of a metaclass pattern.

Instances of metaclasses become ``meta-objects'', which represent a class. The instances of classes are described by the so-called instance description, which is a class-like description at the level of the class methods. A class object must return the instance description when it is passed the special message called instantiator . The class variables and the class methods are visible in the instance description. Both the metaclass and the instance description have super

and self variables, the latter of which are bound to inner-dispatch and outer-dispatch respectively.

Super parts of a metaclass can be instantiated by new-part , which is described in section gif. Super parts of an ``ordinary class'', on the other hand, must be instantiated by the following primitive.

 

(define (new-instance-part class)
 (let ((instantiator (method-lookup class 'instantiator)))
   (instantiator)))

New-instance-part simply extracts the instance-description of the class. This instance description is then instantiated. The parameter class refers to the meta-object, which represents the class. In section gif it is described how entire (non-meta) classes can be instantiated.

I will assume that there is exactly one instance of a metaclass:

(define a-class (new-instance metaclass-name))

Given this assumption it might be tempting to define metaclasses directly as ``singular instances'':

(define a-class
(let ((self ...)
(super super-metaclass))
(let ((class-variable init-value)
...)
...)
self))

If, however, metaclasses are to take part in a metaclass hierarchy, the parts of a metaclasses will, following this approach, be shared with other metaclasses. This is probably not what we want. Consequently we will leave it as a discipline only to instantiate metaclasses once.



next up previous contents
Next: The most General Up: Metaclasses Previous: Metaclasses



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