Meta Object Protocol

The essence of a Metaobject Protocol is simple: every aspect of a program's mapping down onto the lower level substrate (i.e. its compilation and runtime support) is controlled by some object or set of objects following a well-defined protocol. These objects are called metaobjects, because they are about the mapping of the program, rather than objects in the program's primary subject domain. Client programmers can replace one or more of these objects with specialized ones to affect specific aspects of the implementation of specific parts of their program.

Also see Andreas Paepcke, "User-Level Language Crafting": citeseer.ist.psu.edu


How about: make your interpreter (or compiler) available in your program, so that you can change rules for method lookup, variable scoping or whatever else you want in your program. This makes sense, sometimes -- for instance, a better stack tracer that elides calls to the standard library.


Let me take my stab, having (tried to) read the book:

The core of the Metaobject Protocol is to replace the most basic constructs of a language (in the case of OO languages, this would consist of things like how polymorphism is defined, how to treat inheritance (multiple and single), etc.) and make them so they can be configured and changed.

From what I recall, this was important to the implementers of the Common Lisp Object System because they wanted to maintain backwards compatibility with many Lisp implementations, each of which had its own rules regarding inheritance, etc.


Perhaps you can get more from an example. This link gives an implementation of an Eiffel inspired Design By Contract extension to the Common Lisp Object System. A number of the basic mechanism of the OO language are overridden and augmented to do class invariant checking, pre- and post-conditions etc.

-- Lieven Marchand


At first glance, it might seem weird to change how something like method lookup works. But consider an analogy with something more pedestrian: overriding inherited methods. Sometimes you completely replace the superclass' implementation, but just as often you augment it.

This is why a metaobject protocol is of interest to people working on Aspect Oriented Programming. Without a MOP, aspects have to be implemented by weaving, which involves modifying the application source code. A MOP permits another strategy: extending the runtime object system to detect those situations when an aspect is applicable, and interpose the aspect's functionality. You still need a tool to interpret the aspects, but the tool is much simpler with a MOP. --Glenn Vanderburg


I would include not just "every aspect" nor even "most basic constructs" but anything at the virtual machine level. For example, if you can control your memory manager by switching garbage collection on and off, requesting a collection, explicitly freeing objects etc, I'd call that a MOP. -- Dave Harris

I'm not sure I would. It's a Meta Object Protocol, and garbage collection seems more low level and wider in scope than that (in other words those effects are system wide, not really [replacing] one or more of these objects with specialized ones to affect specific aspects of the implementation of specific parts of their program. )

-- PaulHudson

Dave, the people at Xerox who like to talk about this stuff a lot (I don't know whether they're responsible for it or not, but they sure do like to talk about it :-) treat a MOP as a special case of a more general concept: Open Implementation. I think what you're talking about fits in the more general space. --Glenn Vanderburg

Maybe. I was thinking the garbage collector was an object in its own right, belonging to the meta level, and accessed through a protocol, so meta object protocol seemed to fit. Consider allocators in C++. Probably I'm wrong, but I'll leave the discussion in case it helps someone else. -- Dave Harris

No, you were thinking that "anything at the virtual machine level" is MOP; GC was just an "example". Even if you're right about GC, Glenn's comment about "a more general concept" fits the bill.

In a language based upon [our] metaobject protocols, the language implementation itself is structured as an object-oriented program. This allows us to exploit the power of object-oriented programming techniques to to make the language implementation adjustable and flexible. In effect, the resulting implementation does not represent a single point in the overall space of language designs, but an entire region within that space.

See Also:


Pattie Maes has written some wonderful papers about this topic.

My view is that a Metaobject Protocol is a fundamentally important attribute of a Causally Reflective System. These systems virtually always have the ability to treat at least some memory as both code and data. In a Unix environment, this amounts to being able to execute from the data segment or write to the code segment, or both.

An application written, naively, in C or C++ and running on Unix is typically Not Reflective. The application has very limited or no ability to perform computations on itself. For example, its current process state or variable bindings are not accessible to it.

Some systems are Descriptively Reflective. Early examples of this were the C++-based object databases, such as Object Store and Ontos. A Descriptively Reflective system contains a description of itself, and may even use that description, but changing that description merely breaks the system.

The category of systems that I find interesting are Causally Reflective systems, such as Common Lisp and Smalltalk. A Causally Reflective system is written in terms of itself. It contains a description of its own behavior, and uses that description to control its behavior, so that a change to that description changes its behavior.

I suspect that an enterprising PhD candidate could, if it has not already been done, write a thesis proving the hypothesis that a Causally Reflective system must have a metaobject protocol.

MOP and causal reflectivity are rather obviously orthogonal -- causally reflective systems need not expose their descriptions or allow them to be modified, and the descriptions of non-reflective systems can be exposed and modified. And if all you mean is that a causally reflective system necessarily has a description that can be formalized as a data object that the system can interpret -- well, that's how it was just defined, so it wouldn't take a PhD thesis to demonstrate it.


Another source of information on Meta Class programming and Meta Object Protocols is the book "Putting Metaclasses to Work". They even have some simulation code

(written in Java) showing their MOP at work (located at www.amazon.com ).


A metaobject protocol certainly seems powerful. An obvious example would be (I guess) C++ operator overloading, where you can define what otherwise ordinary language elements do to a particular class. Or the java.lang.reflect package in Java, where you can do computation on the structure of your program. (For example, some cool self-configuring systems like Java Beans work by scanning the names of your class's methods for particular naming conventions.)

Operator overloading is no different from overloading any other method name -- it has nothing to do with MOP. Nor does introspection.

But these sorts of features and capabilities are the enemy of learnable, Readable Code, and I find that they are rarely used judiciously.

Well, one example where MOP is often used is to provide persistency. See for example PLOB! (persistent lisp objects) or the DEF-VIEW-CLASS macro provided with Xanaly's lisp. Both these systems let you create CLOS objects whose metaclass is not STANDARD-CLASS, but rather a new, persistent class. The degree of integration into "normal lisp" provided by these tools is simply astounding. I would call that a judicious use indeed. All extremely powerful tools, (and is MOP ever one!) require extreme care and competence by the craftsman.



See original on c2.com