topical media & game development
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
- abstract data type -- interface description
- object generator -- template for creation
- repository -- for sharing resources
- object -- instance of a metaclass
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 in C++ and 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.