The term "MetaObject Protocol" (MOP) originates with Gregor Kiczales's work in implementing CLOS, the object system in Common Lisp. See for example http://www.alu.org/mop/index.html
Briefly, a MOP provides programmatic access to a programming language's implementation of such things as classes, methods, initialization, and so on, both at declaration and execution time.
Such access enables an application programmer to customize or add semantics in cases where the base programming language either does not have the ability, or it doesn't fit the needs of the programmer.
Using a MOP, it is possible to implement functionality such as:
For more information, see his book, "The Art of the Metaobject Protocol". Currently Kiczales is occupied with dumbing down the concept of the MOP into "Aspect Oriented Programming" (AOP) and "Separation of Concerns" (SOC) so that it is accessible to unwashed Java programmers.
This is by no means a full MOP for ECMAScript, for reasons of time, need, and inadequacies in the base language that would make it prohibitively expensive at run time.
A key requirement for a programming language to have a useful MOP is reflection, which has two important parts: introspection, the ability to query about objects and metaobjects, and intercession, the ability to "hook" or alter their runtime behavior. ECMAScript has serious limitations in both of these.
For introspection, some challenges with ECMAScript:
For intercession, there is no:
new
) Furthermore, there are inflexibilities in the language:
Some of these inadequacies may be compensated for easily and efficiently, others cannot.
See also:
Static Public Member Functions | |
void | inherits (Function subclass, Function superclass) |
Perform the prototype idiom of connecting a sublcass Function and a superclass Function. | |
void | add_mixin (Function cls, Function mixin) |
void | assertImplements (Function objclass, Function iface) |
Assert that a given Function constructor implements the functions in the given interface Function. | |
Object | singleton (String funcname, Function ctor) |
Calls the provided constructor and returns the result, if it has never been called before. | |
Function | memoize (Object obj, String funcname, Function func) |
Returns a replacement function that proxies for the passed-in one, and ensures that the underlying function is only called once for any give set of arguments. | |
Function | lazyChooseMethod (Object obj, String memname, Function getfunc) |
Return a function which will set the actual function implementation the first time it is called (and then call the real implementation). | |
Object | memoizeNew1 (Object cache, Function ctor, Object arg1) |
Convenience to memoize a constructor with a single argument. | |
Object | memoizeNew1 (Object cache, Function ctor, Object arg1, Object arg2) |
Same as memoizeNew1 but for 2 arguments. | |
Object | onceonly (Object cache, String key, Function func) |
Simple low-level utility for once-only semantics. | |
Function | combineMethods (Function f, Function g) |
A method combinator which returns a method which calls f then g: f.apply(this, arguments); g.apply(this, arguments) If f throws an exception, then g is not run. | |
void | afterMethod (Object obj, String methname, Function aftermeth, Boolean must_exist) |
Arrange for method aftermeth to be called whenever the method named methname of object obj is called. | |
void | addMethodAdvice (Object obj, String methname, Function advice, String advice_kind, String precedence, Boolean meth_must_exist) |
Add some advice at a method call pointcut. | |
Boolean | removeMethodAdvice (Object obj, String methname, Function advice, String advice_kind, Boolean missing_ok) |
Remove some advice. | |
Boolean | removeAllMethodAdvice (Object obj, String methname, Boolean missing_ok) |
Remove all advice from a method, restoring it to its initial state. | |
Object | initNamed (Object obj, Object values, Object names, Boolean nullDefault) |
Initialize the object obj's instance variables from values. |
|
Add some advice at a method call pointcut. If advice_kind is 'before' or 'after', then the supplied function advice() must expect the same arguments as the wrapped method call (and with 'this' bound to the wrapped aobject obj). If advice_kind is 'around', then the supplied function advice() is called with a single argument which is an instance of burst.MethodInvocation. That instance mi has instance variables mi.object and mi.args which can be modified, and a method mi.proceed() which can (and generally should) be called to find out what any other wrapped advice will return. Unlike 'before' and 'after', an 'around' advice can change the overall result (it can return something other than the result it gets from calling proceed()). Note that we are far from a complete AOP implementation, lacking for example:
Some discussion of advice for other languages:
|
|
Arrange for method aftermeth to be called whenever the method named methname of object obj is called. If instead of passing in a single instance foo, you pass in foo.prototype, then this hooking will apply to all instances. Naturally, aftermeth must expect the same arguments as methname. This function uses combineMethods. If the first method throws an exception, aftermeth is not called. Furthermore, there is no way to undo this operation. However, this implementation is efficient at run time. See also addMethodAdvice
|
|
Assert that a given Function constructor implements the functions in the given interface Function. It does this by comparing the prototype objects of the two of them. throws if it finds any missing functions. |
|
Perform the prototype idiom of connecting a sublcass Function and a superclass Function. See also many other idioms, for example at http://bclary.com/log/2002/12/08/1.html |
|
Initialize the object obj's instance variables from values. If names, the function throws if there is a property in values but not in names. Also names values are booleans, true if the value must be provided, and false if not. If obj already has a value for any given key, it is overwritten.
|
|
Return a function which will set the actual function implementation the first time it is called (and then call the real implementation).
|
|
Returns a replacement function that proxies for the passed-in one, and ensures that the underlying function is only called once for any give set of arguments. example with a static function:
|
|
Convenience to memoize a constructor with a single argument. If the constructor has been called before with the same argument, that previous instance is returned.
|
|
Simple low-level utility for once-only semantics. Works only with functions of no arguments. |
|
Remove some advice. If it is found, it is removed and we return true. If it is not found, we return false if missing_ok, otherwise throw. |