topical media & game development

talk show tell print

object-oriented programming

Meta-level architectures

Another weakness of the classical object model (or perhaps one of its strengths) is that the concept of a class easily lends itself to being overloaded with additional meanings and features such as class variables and metaclasses. These notions lead to extensions to the original class/instance scheme that are hard to unify in a single elegant framework. In this section we will study a proposal based on a reflexive relation between classes and objects. Depending on one's perspective, a class may either be regarded as a kind of abstract data type (specifying the operational interface of its object instances) or, more pragmatically, as a template for object creation (that is, a means to generate new instances).

The class concept


slide: The concept of class

In addition, however, in a number of systems A class may be used as a repository for sharing class-wide resources. For example, the Smalltalk language allows the definition of class variables that are accessible to all instances of the class. See slide 5-class.

Class variables

Clearly, the use of class variables violates what we have called the distribution boundary in section multi-paradigm, since it allows objects to reach out of their encapsulation borders. Class variables may also be employed in C++ and Java by defining data members as static. Apart from class variables, Smalltalk also supports the notion of class methods, which may be regarded as routines having the class and its instances as their scope. Class methods in Smalltalk are typically used for the creation and initialization of new instances of the class for which they are defined. In C++ and Java, creation and initialization is taken care of by the constructor(s) of a class, together with the (system supplied) new operator. Class methods, in C++ and Java, take the form of static member functions that are like ordinary functions (apart from their restricted scope and their calling syntax, which is of the form class::member(...) in C++ and class.member(...) in Java). Contrary to classes in C++ and Java, classes in Smalltalk have a functionality similar to that of objects. Classes in Smalltalk provide encapsulation (encompassing class variables and class methods) and message passing (for example for the creation and initialization of new instances). To account for this object-like behavior, the designers of Smalltalk have introduced the notion of metaclass of which a class is an instance.

Metaclasses

In the classical object model, two relations play a role when describing the architectural properties of a system. The first relation is the instance relation to indicate that an object O is an instance of a class C. The second (equally important) relation is the inheritance relation, which indicates that a class C is a subclass (or derived from) a given (ancestor) class P. When adopting the philosophy everything is an object together with the idea that each object is an instance of a class (as the developers of Smalltalk did), we evidently get into problems when we try to explain the nature (and existence) of a class.

To be an object, a class itself must be an instance of a class (which for convenience we will call a metaclass). Take, for example, the class Point. This class must be an instance of a (meta)class (say Class) which in its turn must be an instance of a (meta) class (say MetaClass), and so on. Clearly, following the instance relation leads to an infinite regress. Hence, we must postulate some system-defined MetaClass (at a certain level) from which to instantiate the (metaclasses of) actual classes such as Point.



slide: Meta architectures

The figure in slide meta-architecture(a) is a (more or less) accurate rendering of the solution provided by Smalltalk. We may add additional flexibility by allowing user-defined metaclasses that may refine the behavior of the system-defined metaclass Class. This is the solution chosen for Loops, see  [LOOPS]. Thus far we have traced the instance relation which leads (following the reversed arrows) from top to bottom, from metaclasses to actual object instances. As pictured in the diagram (a) above, the inheritance relation (followed in the same manner) goes in exactly the opposite direction, having the class Object at the root of the inheritance hierarchy. For example, the class Point (while being an instance of the metaclass Class) is derived by inheritance from the class Object. Similarly, the (meta)class Class itself inherits from the class Object, and in its turn the system-defined metaclass MetaClass inherits from Class. As for the user-defined metaclasses, these may be thought of as inheriting from the system-defined metaclass Class. Apart from being slightly confusing, Smalltalk's meta-architecture is rather inelegant due to the magic (that is system-defined) number of meta levels. In the following, we will study a means to overcome this inelegancy.

Reflection

 [Cointe87] proposes an architecture that unifies the notions of object, class and metaclass, while allowing metaclasses to be defined at an arbitrary level. The key to this solution lies in the postulates characterizing the behavior of an object-oriented system given in slide 5-postulates.

Postulates -- class-based languages

  • everything is an object
  • every object belongs to a class
  • every class inherits from the class Object
  • class variables of an object are instance variables of its class

slide: Class-based languages -- postulates

The first three postulates are quite straightforward. They agree with the assumptions underlying Smalltalk. The last postulate, however, stating that a class variable of an object must be an instance variable of the objects class (taken as an object), imposes a constraint of a self-recurrent or reflexive nature. This recurrence is pictured in slide meta-architecture(b), which displays the object Class as an instance of itself (that is the class Class). In other respects, the diagram is similar to the diagram depicting the (meta) architecture of Smalltalk and Loops. To indicate how such a reflective relation may be implemented,  [Cointe87] introduces a representation of objects involving the attributes name (to indicate the class of the object), supers (to indicate its ancestor(s)), iv (to list the instance variables of the object) and methods (to store the methods belonging to the object). In this scheme of representation, the system-defined metaclass Class is precisely the object reflecting its own structure in the values of its attributes, as depicted above. Every instance of Class may assign values to its instance variables (contained in iv) that are appropriate to the instances that will be created from it. In general, a metaclass is an object having at least the attributes of Class (and possibly more). See slide 5-reflex-class.

Reflective definition of Class


   name         Class
   supers      (Object)
   iv     (name supers iv methods)
   methods      (new ...)
  

slide: A reflective definition of Class

Using this scheme, an arbitrary towering of metaclasses may be placed on top of concrete classes, thus allowing the software developer to squeeze out the last bit of differential programming. Elegant indeed, although it is doubtful whether many programmers will endeavor upon such a route. A nice example of employing (customized) metaclasses, however, is given in  [Malenfant89], where metaclasses are used to define the functionality of distribution and communication primitives employed by concrete classes.

(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.