From: Pascal Costanza
Newsgroups: comp.lang.lisp
Subject: Re: Art of MetaObject Protocol and Reflection (Java, C#, etc.)
Date: Sun, 18 Sep 2005 15:06:57 +0200
Lines: 114
Message-ID: <3p573iF8lvf2U1@individual.net>
References: <87slw2wted.fsf@ileriseviye.org>
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
X-Trace: individual.net BtB6JRtZRY+d/AVQvMK4tQYXPICHQocOqxprpIqueYmCP8DnBI
In-Reply-To:  <87slw2wted.fsf@ileriseviye.org>
Xref: reader0.news.be.easynet.net comp.lang.lisp:103711

Emre Sevinc wrote:
> I'm reading The Art of MetaObject Protocol and try to
> understand how it extends CLOS.
>
> I've read about 60 pages and a question came to my mind:
>
> Authors talk about dynamic class creation, inspecting
> classes at runtime, etc. How are these features compared
> to "reflection" in Java, C#, etc? I don't know much
> about that but as far as I know Java and C# programmers
> can also introspect classes during runtime, create classes
> on-the-fly, etc. which they call the "reflection" property
> of their language, right?
>
> Is MetaObject protocol for CLOS similar to "reflection"
> in those languages? Is it something more, something less?
> Has some advantages that reflection in Java and C# don't
> have?

Reflection originally means both introspection and intercession (these
are the technical terms). Introspection allows you to find out
information about elements of your program - classes, variables,
methods, functions, etc. What the Java folks called reflection in the
beginning is indeed just introspection.

Intercession is a way to modify the characteristics of the elements of
your program. So intercession allows you to change the properties of
classes, variables, methods, functions, etc.

Reflection was originally "invented" by Brian Smith in the form of
procedural reflection - i.e., you basically have a notion of interceding
procedure calls, inspecting the environment(s) that are active during
those calls, and possibly changing the way the program continues its
execution. If you allow programmers to intercede at each and every
single step of your program execution, though, your programs slow down
considerably, even if noone intercedes anything, because the runtime has
to continually check whether someone wants to do something additionally
or not.

For that reason, Brian Smith and Jim des Rivieres (if I understand
correctly, it was those two guys) implemented reflection by dividing the
program into levels, so that one could specify at which level you want
to intercede the program execution. The levels for which you don't
intercede can be executed "at full speed", while the other levels have
to run your additional code.

It was then discovered that this actually leads to an object-oriented
design of the reflection facilities, because the notion of dividing
programs into levels and specifying different behavior at different
levels is more or less exactly what you do in an object-oriented
hierarchy. So, for example, in a class hierarchy, the classes higher up
in the hierarchy define the "base" behavior while the classes that
inherit from those superclasses define the additional behavior. Next,
when you disallow programmers from changing the definitions of the base
classes, you can actually implement the runtime much more efficiently
because you can check whether a given object is an instance of a base
class or not, and if it's an instance of a base class you can run
optimized versions of the methods defined on those classes that don't
call the (non-existent) code of subclasses.

The CLOS Metaobject Protocol is essentially that idea carried through
the end.

Java reflection is not even close. Java has meta-level objects that
describe classes, methods, fields, etc., but there is no way to change
them. However, there are some little opportunities to get something
along the lines of a full-blown metaobject protocol:

- You can implement proxy classes - see
java.lang.reflect.InvocationHandler. This allows you to intercept method
calls to objects.
- There is a debugging API that allows you to change the definition of a
class (including its methods) at runtime, which in principle allows you
to add additional behavior to methods.
- Finally, you can intercept class loading and modify the bytecode for a
class before it enters the virtual machine. This is the most powerful
way to achieve similar effects as those of a MOP, but is not a proper
MOP in its own right. (You don't specify the new behavior as methods for
meta-level classes, but you rather just modify a byte stream.)

The latter has been used to define proper (load-time) metaobject
protocols, though, for example Javassist and Reflex.

These things are much more complicated to achieve in Java than in CLOS,
though, even with such frameworks. Furthermore, I am convinced that a
full runtime metaobject protocol is essential. (Load-time or
compile-time metaobject protocol can lead to more efficient code, that's
why they have been pursued in the past, but I think these efficiency
gains are too small to be important enough in the long run. The
flexibility of a runtime metaobject protocal is more important because
it gives you more expressivity IMHO.)

I think the situation for C# is similar to that for Java, although they
have added a few more practical stuff from the beginning. For example,
.NET comes with a library that gives you a (modifiable) representation
of their bytecode format, and I recall seeing a presentation about a
load-time bytecode modification approach for .NET that was a lot simpler
than what I have seen in the Java world. But that's all I can tell about C#.

Metaobject protocols exist for other languages (and also for other
domains than language implementations). A relatively old list of
metaobject protocols is given at
http://www2.parc.com/csl/groups/sda/projects/mops/existing-mops.html

Eric Tanter provides an excellent and recent overview of reflection,
metaobject protocols and aspect-oriented programming (which is another
form of reflection, in a sense) in his PhD thesis about Reflex - see
http://www.dcc.uchile.cl/~etanter/

Pascal
  • meta_object_protocol.txt
  • Last modified: 2007-06-12 18:04
  • by 127.0.0.1