29.2. Overview
Prev | Chapter 29. Meta-Object Protocol | Next

## 29.2. Overview

### 29.2.1. Metaobjects

For each kind of program element there is a corresponding basic metaobject class . These are the classes: `CLASS`, `CLOS:SLOT-DEFINITION`, `GENERIC-FUNCTION`, `METHOD` and `METHOD-COMBINATION`. A metaobject class is a subclass of exactly one of these classes. The results are undefined if an attempt is made to define a `CLASS` that is a subclass of more than one basic metaobject class. A metaobject is an instance of a metaobject class.

Each metaobject represents one program element. Associated with each metaobject is the information required to serve its role. This includes information that might be provided directly in a user interface macro such as `DEFCLASS` or `DEFMETHOD`. It also includes information computed indirectly from other metaobjects such as that computed from class inheritance or the full set of methods associated with a generic function.

Much of the information associated with a metaobject is in the form of connections to other metaobjects. This interconnection means that the role of a metaobject is always based on that of other metaobjects. As an introduction to this interconnected structure, this section presents a partial enumeration of the kinds of information associated with each kind of metaobject. More detailed information is presented later.

#### 29.2.1.1. Classes

A class metaobject determines the structure and the default behavior of its instances. The following information is associated with class metaobjects:

- The name, if there is one, is available as an object.
- The direct subclasses, direct superclasses and class precedence list are available as lists of class metaobjects.
- The slots defined directly in the class are available as a list of direct slot definition metaobjects. The slots which are accessible in instances of the class are available as a list of effective slot definition metaobjects.
- The methods which use the class as a specializer, and the generic functions associated with those methods are available as lists of method and generic function metaobjects respectively.
- The documentation is available as a `STRING` or `NIL`.

See also Section 29.3, “Classes”

#### 29.2.1.2. Slot Definitions

A slot definition metaobject contains information about the definition of a slot. There are two kinds of slot definition metaobjects: A direct slot definition metaobject is used to represent the direct definition of a slot in a class. This corresponds roughly to the slot specifiers found in `DEFCLASS` forms. An effective slot definition metaobject is used to represent information, including inherited information, about a slot which is accessible in instances of a particular class.

Associated with each class metaobject is a list of direct slot definition metaobjects representing the slots defined directly in the class. Also associated with each class metaobject is a list of effective slot definition metaobjects representing the set of slots accessible in instances of that class.

The following information is associated with both direct and effective slot definitions metaobjects:

- The name, allocation, and type are available as forms that could appear in a `DEFCLASS` form.
- The initialization form, if there is one, is available as a form that could appear in a `DEFCLASS` form. The initialization form together with its lexical environment is available as a function of no arguments which, when called, returns the result of evaluating the initialization form in its lexical environment. This is called the initfunction of the slot.
- The slot filling initialization arguments are available as a list of symbols.
- The documentation is available as a `STRING` or `NIL`.

Certain other information is only associated with direct slot definition metaobjects. This information applies only to the direct definition of the slot in the class (it is not inherited).

- The function names of those generic functions for which there are automatically generated reader and writer methods. This information is available as lists of function names. Any accessors specified in the `DEFCLASS` form are broken down into their equivalent readers and writers in the direct slot definition.

Information, including inherited information, which applies to the definition of a slot in a particular class in which it is accessible is associated only with effective slot definition metaobjects.

- For certain slots, the location of the slot in instances of the class is available.

See also Section 29.4, “Slot Definitions”

#### 29.2.1.3. Generic Functions

A generic function metaobject contains information about a generic function over and above the information associated with each of the generic function's methods.

- The name is available as a function name.
- The methods associated with the generic function are available as a list of method metaobjects.
- The default class for this generic function's method metaobjects is available as a class metaobject.
- The lambda list is available as a `LIST`.
- The method combination is available as a method combination metaobject.
- The argument precedence order is available as a permutation of those symbols from the lambda list which name the required arguments of the generic function.

- The “declarations” are available as a list of declaration specifiers.

  ### Note

  There is a slight misnomer in the naming of functions and options in this document: Where the term “declaration” is used, actually a declaration specifier is meant.

- The documentation is available as a `STRING` or `NIL`.

See also Section 29.5, “Generic Functions”

#### 29.2.1.4. Methods

A method metaobject contains information about a specific `METHOD`.

- The qualifiers are available as a `LIST` of of non-`NIL` atoms.
- The lambda list is available as a `LIST`.
- The specializers are available as a list of specializer metaobjects.
- The function is available as a `FUNCTION`. This function can be applied to arguments and a list of next methods using `APPLY` or `FUNCALL`.
- When the method is associated with a generic function, that generic function metaobject is available. A method can be associated with at most one generic function at a time.
- The documentation is available as a `STRING` or `NIL`.

See also Section 29.6, “Methods”

#### 29.2.1.5. Specializers

A specializer metaobject represents the specializers of a `METHOD`. class metaobjects are themselves specializer metaobjects. A special kind of specializer metaobject is used for `EQL` specializers.

See also Section 29.8, “Specializers”

#### 29.2.1.6. Method Combinations

A method combination metaobject represents the information about the method combination being used by a generic function.

### Note

This document does not specify the structure of method combination metaobjects.

See also Section 29.9, “Method Combinations”

### 29.2.2. Inheritance Structure of Metaobject Classes

Figure 29.1. Inheritance structure of metaobject classes

The inheritance structure of the specified metaobject classes is shown in Table 29.1, “Direct Superclass Relationships Among The Specified Metaobject Classes”. The class of every class shown is `STANDARD-CLASS` except for the classes `T` and `FUNCTION`, which are instances of the class `BUILT-IN-CLASS`, and the classes `GENERIC-FUNCTION` and `STANDARD-GENERIC-FUNCTION`, which are instances of the class `CLOS:FUNCALLABLE-STANDARD-CLASS`.

Table 29.1. Direct Superclass Relationships Among The Specified Metaobject Classes

Metaobject Class | Abstract | Subclassable | Direct Superclasses
--- | --- | --- | ---
`STANDARD-OBJECT` | no | yes | (`T`)
`CLOS:FUNCALLABLE-STANDARD-OBJECT` | no | yes | (`STANDARD-OBJECT` `FUNCTION`)
`CLOS:METAOBJECT` | yes | no | (`STANDARD-OBJECT`)
`GENERIC-FUNCTION` | yes | no | (`CLOS:METAOBJECT` `CLOS:FUNCALLABLE-STANDARD-OBJECT`)
`STANDARD-GENERIC-FUNCTION` | no | yes | (`GENERIC-FUNCTION`)
`METHOD` | yes | no | (`CLOS:METAOBJECT`)
`STANDARD-METHOD` | no | yes | (`METHOD`)
`CLOS:STANDARD-ACCESSOR-METHOD` | yes | no | (`STANDARD-METHOD`)
`CLOS:STANDARD-READER-METHOD` | no | yes | (`CLOS:STANDARD-ACCESSOR-METHOD`)
`CLOS:STANDARD-WRITER-METHOD` | no | yes | (`CLOS:STANDARD-ACCESSOR-METHOD`)
`METHOD-COMBINATION` | yes | no | (`CLOS:METAOBJECT`)
`CLOS:SLOT-DEFINITION` | yes | no | (`CLOS:METAOBJECT`)
`CLOS:DIRECT-SLOT-DEFINITION` | yes | no | (`CLOS:SLOT-DEFINITION`)
`CLOS:EFFECTIVE-SLOT-DEFINITION` | yes | no | (`CLOS:SLOT-DEFINITION`)
`CLOS:STANDARD-SLOT-DEFINITION` | yes | no | (`CLOS:SLOT-DEFINITION`)
`CLOS:STANDARD-DIRECT-SLOT-DEFINITION` | no | yes | (`CLOS:STANDARD-SLOT-DEFINITION` `CLOS:DIRECT-SLOT-DEFINITION`)
`CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION` | no | yes | (`CLOS:STANDARD-SLOT-DEFINITION` `CLOS:EFFECTIVE-SLOT-DEFINITION`)
`CLOS:SPECIALIZER` | yes | no | (`CLOS:METAOBJECT`)
`CLOS:EQL-SPECIALIZER` | no | no | (`CLOS:SPECIALIZER`)
`CLASS` | yes | no | (`CLOS:SPECIALIZER`)
`BUILT-IN-CLASS` | no | no | (`CLASS`)
`CLOS:FORWARD-REFERENCED-CLASS` | no | no | (`CLASS`)
`STANDARD-CLASS` | no | yes | (`CLASS`)
`CLOS:FUNCALLABLE-STANDARD-CLASS` | no | yes | (`CLASS`)

Each class with a “yes” in the “Abstract” column is an abstract class and is not intended to be instantiated. The results are undefined if an attempt is made to make an instance of one of these classes with `MAKE-INSTANCE`.

Each class with a “yes” in the “Subclassable” column can be used as direct superclass for portable programs. It is not meaningful to subclass a class that has a “no” in this column.

### Implementation dependent: only in CLISP

The class `METHOD` is also subclassable: It is possible to create subclasses of `METHOD` that do not inherit from `STANDARD-METHOD`.

### Implementation dependent: only in CLISP and some other implementations

The class `CLOS:FUNCALLABLE-STANDARD-OBJECT`'s class precedence list contains `FUNCTION` before `STANDARD-OBJECT`, not after `STANDARD-OBJECT`. This is the most transparent way to realize the [ANSI CL standard] requirement (see the [ANSI CL standard] section 4.2.2 “Type Relationships”) that `GENERIC-FUNCTION`'s class precedence list contains `FUNCTION` before `STANDARD-OBJECT`.

The classes `STANDARD-CLASS`, `CLOS:STANDARD-DIRECT-SLOT-DEFINITION`, `CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION`, `STANDARD-METHOD`, `CLOS:STANDARD-READER-METHOD`, `CLOS:STANDARD-WRITER-METHOD` and `STANDARD-GENERIC-FUNCTION` are called standard metaobject classes. For each kind of metaobject, this is the class the user interface macros presented in the CLOS use by default. These are also the classes on which user specializations are normally based.

The classes `BUILT-IN-CLASS`, `CLOS:FUNCALLABLE-STANDARD-CLASS` and `CLOS:FORWARD-REFERENCED-CLASS` are special-purpose class metaobject classes. Built-in classes are instances of the class `BUILT-IN-CLASS`. The class `CLOS:FUNCALLABLE-STANDARD-CLASS` provides a special kind of instances described in Section 29.10.2, “Funcallable Instances”. When the definition of a class references another class which has not yet been defined, an instance of `CLOS:FORWARD-REFERENCED-CLASS` is used as a stand-in until the class is actually defined.

### Implementation of class `CLOS:FORWARD-REFERENCED-CLASS` in CLISP

The class `CLOS:FORWARD-REFERENCED-CLASS` is implemented in a way that fixes several flaws in the [AMOP] specification.

It is not a subclass of `CLASS` and `CLOS:SPECIALIZER`, just a subclass of `CLOS:METAOBJECT`, because forward references to classes are not classes and cannot be used as specializers of methods. An [AMOP] compatibility mode is provided, however, if you set the variable `CUSTOM:*FORWARD-REFERENCED-CLASS-MISDESIGN*` to `T`. In this mode, `CLOS:FORWARD-REFERENCED-CLASS` is formally a subclass of `CLASS` and `CLOS:SPECIALIZER`, but the behaviour of `CLOS:FORWARD-REFERENCED-CLASS` instances is the same.

The [AMOP] says that the first argument of `CLOS:ENSURE-CLASS-USING-CLASS` can be a `CLOS:FORWARD-REFERENCED-CLASS`. But from the description of `CLOS:ENSURE-CLASS`, it is clear that it can only be a class returned by `FIND-CLASS`, and [ANSI CL standard] `FIND-CLASS` cannot return a `CLOS:FORWARD-REFERENCED-CLASS`.

The [AMOP] says that `CLOS:ENSURE-CLASS-USING-CLASS` creates a `CLOS:FORWARD-REFERENCED-CLASS` for not-yet-defined class symbols among the direct-superclasses list. But this leads to many `CLOS:FORWARD-REFERENCED-CLASS` with the same name (since they cannot be stored and retrieved through `FIND-CLASS`), and since `CHANGE-CLASS` preserves the `EQ`-ness, after the class is defined, we have many class objects with the same name.

In the direct-superclasses list of non-finalized classes, `CLOS:FORWARD-REFERENCED-CLASS` instances can occur, denoting classes that have not yet been defined. When or after such a class gets defined, the `CLOS:FORWARD-REFERENCED-CLASS` instance is replaced with the real class. CLISP uses simple object replacement, not `CHANGE-CLASS`, in this process.

The class `STANDARD-OBJECT` is the default direct superclass of the class `STANDARD-CLASS`. When an instance of the class `STANDARD-CLASS` is created, and no direct superclasses are explicitly specified, it defaults to the class `STANDARD-OBJECT`. In this way, any behavior associated with the class `STANDARD-OBJECT` will be inherited, directly or indirectly, by all instances of the class `STANDARD-CLASS`. A subclass of `STANDARD-CLASS` may have a different class as its default direct superclass, but that class must be a subclass of the class `STANDARD-OBJECT`.

The same is true for `CLOS:FUNCALLABLE-STANDARD-CLASS` and `CLOS:FUNCALLABLE-STANDARD-OBJECT`.

The class `CLOS:SPECIALIZER` captures only the most basic behavior of method specializers, and is not itself intended to be instantiated. The class `CLASS` is a direct subclass of `CLOS:SPECIALIZER` reflecting the property that classes by themselves can be used as method specializers. The class `CLOS:EQL-SPECIALIZER` is used for `EQL` specializers.

#### 29.2.2.1. Implementation and User Specialization

The purpose of the Metaobject Protocol is to provide users with a powerful mechanism for extending and customizing the basic behavior of the CLOS. As an object-oriented description of the basic CLOS behavior, the Metaobject Protocol makes it possible to create these extensions by defining specialized subclasses of existing metaobject classes.

The Metaobject Protocol provides this capability without interfering with the implementor's ability to develop high-performance implementations. This balance between user extensibility and implementor freedom is mediated by placing explicit restrictions on each. Some of these restrictions are general---they apply to the entire class graph and the applicability of all methods. These are presented in this section.

The following additional terminology is used to present these restrictions:

- Metaobjects are divided into three categories. Those defined in this document are called specified; those defined by an implementation but not mentioned in this document are called implementation-specific; and those defined by a portable program are called portable.
- A class `i` is interposed between two other classes `k1` and `k2` if and only if there is some path, following direct superclasses, from the class `k1` to the class `k2` which includes `i`.
- A method is specialized to a class if and only if that class is in the list of specializers associated with the method; and the method is in the list of methods associated with some generic function.
- In a given implementation, a specified method is said to have been promoted if and only if the specializers of the method, `x1` ... `xn`, are defined in this specification as the classes `k1` ... `kn`, but in the implementation, one or more of the specializers `xl`, is a superclass of the class given in the specification `kl`.

- For a given generic function and set of arguments, a method `k2` extends a method `k1` if and only if:

  1. `k1` and `k2` are both associated with the given generic function
  2. `k1` and `k2` are both applicable to the given arguments,
  3. the specializers and qualifiers of the methods are such that when the generic function is called, `k2` is executed before `k1`,
  4. `k1` will be executed if and only if `CALL-NEXT-METHOD` is invoked from within the body of `k2` and
  5. `CALL-NEXT-METHOD` is invoked from within the body of `k2`, thereby causing `k1` to be executed.

- For a given generic function and set of arguments, a method `k2` overrides a method `k1` if and only if conditions i through iv above hold and, instead of v,

  6. `CALL-NEXT-METHOD` is not invoked from within the body of `k2`, thereby preventing `k1` from being executed.

##### 29.2.2.1.1. Restrictions on Portable Programs

Portable programs are allowed to define subclasses of specified classes, and are permitted to define methods on specified generic functions, with the following restrictions:

- Portable programs must not redefine any specified classes, generic functions, methods or method combinations. Any method defined by a portable program on a specified generic function must have at least one specializer that is neither a specified class nor an `EQL` specializer whose associated value is an instance of a specified class.
- Portable programs may define methods that extend specified methods unless the description of the specified method explicitly prohibits this. Unless there is a specific statement to the contrary, these extending methods must return whatever value was returned by the call to `CALL-NEXT-METHOD`.

- Portable programs may define methods that override specified methods only when the description of the specified method explicitly allows this. Typically, when a method is allowed to be overridden, a small number of related methods will need to be overridden as well.

  An example of this is the specified methods on the generic functions `CLOS:ADD-DEPENDENT`, `CLOS:REMOVE-DEPENDENT` and `CLOS:MAP-DEPENDENTS`. Overriding a specified method on one of these generic functions requires that the corresponding method on the other two generic functions be overridden as well.

- Portable methods on specified generic functions specialized to portable metaobject classes must be defined before any instances of those classes (or any subclasses) are created, either directly or indirectly by a call to `MAKE-INSTANCE`. Methods can be defined after instances are created by `ALLOCATE-INSTANCE` however. Portable metaobject classes cannot be redefined.

  ### Note

  The purpose of this last restriction is to permit implementations to provide performance optimizations by analyzing, at the time the first instance of a metaobject class is initialized, what portable methods will be applicable to it. This can make it possible to optimize calls to those specified generic functions which would have no applicable portable methods.

  ### Implementation dependent: only in CLISP

  When a metaobject class is redefined, CLISP issues a `WARNING` that the redefinition has no effect. To avoid this warning, place all metaobject class definitions in a separate file, compile it in a separate session (because `DEFCLASS` in CLISP is evaluated at compile time too; see Section 29.2.3.2, “Compile-file Processing of Specific User Interface Macros”), and then `LOAD` it only once per session.

The results are undefined if any of these restrictions are violated.

### Note

The specification technology used in this document needs further development. The concepts of object-oriented protocols and subclass specialization are intuitively familiar to programmers of object-oriented systems; the protocols presented here fit quite naturally into this framework. Nonetheless, in preparing this document, we have found it difficult to give specification-quality descriptions of the protocols in a way that makes it clear what extensions users can and cannot write. Object-oriented protocol specification is inherently about specifying leeway, and this seems difficult using current technology.

##### 29.2.2.1.2. Restrictions on Implementations

Implementations are allowed latitude to modify the structure of specified classes and methods. This includes: the interposition of implementation-specific classes; the promotion of specified methods; and the consolidation of two or more specified methods into a single method specialized to interposed classes.

Any such modifications are permitted only so long as for any portable class `k` that is a subclass of one or more specified classes `k1` ... `kn`, the following conditions are met:

- In the actual class precedence list of `k`, the classes `k1` ... `kn` must appear in the same order as they would have if no implementation-specific modifications had been made.
- The method applicability of any specified generic function must be the same in terms of behavior as it would have been had no implementation-specific changes been made. This includes specified generic functions that have had portable methods added. In this context, the expression “the same in terms of behavior” means that methods with the same behavior as those specified are applicable, and in the same order.
- No portable class `k` may inherit, by virtue of being a direct or indirect subclass of a specified class, any slot for which the name is a symbol accessible in the “COMMON-LISP-USER” package or exported by any package defined in the [ANSI CL standard].
- Implementations are free to define implementation-specific before- and after-methods on specified generic functions. Implementations are also free to define implementation-specific around-methods with extending behavior.

### 29.2.3. Processing of the User Interface Macros

A list in which the first element is one of the symbols `DEFCLASS`, `DEFMETHOD`, `DEFGENERIC`, `DEFINE-METHOD-COMBINATION`, `CLOS:GENERIC-FUNCTION`, `CLOS:GENERIC-FLET` or `CLOS:GENERIC-LABELS`, and which has proper syntax for that macro is called a user interface macro form. This document provides an extended specification of the `DEFCLASS`, `DEFMETHOD` and `DEFGENERIC` macros.

The user interface macros `DEFCLASS`, `DEFGENERIC` and `DEFMETHOD` can be used not only to define metaobjects that are instances of the corresponding standard metaobject class, but also to define metaobjects that are instances of appropriate portable metaobject classes. To make it possible for portable metaobject classes to properly process the information appearing in the macro form, this document provides a limited specification of the processing of these macro forms.

User interface macro forms can be evaluated or compiled and later executed. The effect of evaluating or executing a user interface macro form is specified in terms of calls to specified functions and generic functions which provide the actual behavior of the macro. The arguments received by these functions and generic functions are derived in a specified way from the macro form.

Converting a user interface macro form into the arguments to the appropriate functions and generic functions has two major aspects: the conversion of the macro argument syntax into a form more suitable for later processing, and the processing of macro arguments which are forms to be evaluated (including method bodies).

In the syntax of the `DEFCLASS` macro, the `initform` and `default-initarg-initial-value-form` arguments are forms which will be evaluated one or more times after the macro form is evaluated or executed. Special processing must be done on these arguments to ensure that the lexical scope of the forms is captured properly. This is done by building a function of zero arguments which, when called, returns the result of evaluating the form in the proper lexical environment.

In the syntax of the `DEFMETHOD` macro the `forms` argument is a list of forms that comprise the body of the method definition. This list of forms must be processed specially to capture the lexical scope of the macro form. In addition, the lexical functions available only in the body of methods must be introduced. To allow this and any other special processing (such as slot access optimization), a specializable protocol is used for processing the body of methods. This is discussed in Section 29.6.3.1.1, “Processing Method Bodies”.

#### 29.2.3.1. Compile-file Processing of the User Interface Macros

It is a common practice for Common Lisp compilers, while processing a file or set of files, to maintain information about the definitions that have been compiled so far. Among other things, this makes it possible to ensure that a global macro definition (`DEFMACRO` form) which appears in a file will affect uses of the macro later in that file. This information about the state of the compilation is called the `COMPILE-FILE` environment.

When compiling files containing CLOS definitions, it is useful to maintain certain additional information in the `COMPILE-FILE` environment. This can make it possible to issue various kinds of warnings (e.g., lambda list congruence) and to do various performance optimizations that would not otherwise be possible.

At this time, there is such significant variance in the way existing Common Lisp implementations handle `COMPILE-FILE` environments that it would be premature to specify this mechanism. Consequently, this document specifies only the behavior of evaluating or executing user interface macro forms. What functions and generic functions are called during `COMPILE-FILE` processing of a user interface macro form is not specified. Implementations are free to define and document their own behavior. Users may need to check implementation-specific behavior before attempting to compile certain portable programs.

#### 29.2.3.2. Compile-file Processing of Specific User Interface Macros

`DEFCLASS`

  Section 29.3.1, “Macro `DEFCLASS`”

  ### Implementation dependent: only in CLISP

  CLISP evaluates `DEFCLASS` forms also at compile time.

`DEFMETHOD`

  Section 29.6.3.1, “Macro `DEFMETHOD`”

  ### Implementation dependent: only in CLISP

  CLISP does not evaluate `DEFMETHOD` forms at compile time except as necessary for signature checking.

`DEFGENERIC`

  Section 29.5.3.1, “Macro `DEFGENERIC`”

  ### Implementation dependent: only in CLISP

  CLISP does not evaluate `DEFGENERIC` forms at compile time except as necessary for signature checking.

### 29.2.4. Metaobject Initialization Protocol

Like other objects, metaobjects can be created by calling `MAKE-INSTANCE`. The initialization arguments passed to `MAKE-INSTANCE` are used to initialize the metaobject in the usual way. The set of legal initialization arguments, and their interpretation, depends on the kind of metaobject being created. Implementations and portable programs are free to extend the set of legal initialization arguments. Detailed information about the initialization of each kind of metaobject are provided in the appropriate sections:

- Section 29.3.5.1, “Initialization of class metaobjects”
- Section 29.3.5.2, “Reinitialization of class metaobjects”
- Section 29.5.3.3, “Initialization of generic function metaobjects”
- Section 29.3.4, “Class Finalization Protocol”
- Section 29.10.1, “Instance Structure Protocol”
- Section 29.10.2, “Funcallable Instances”
- Section 29.5.3.2, “Generic Function Invocation Protocol”
- Section 29.11, “Dependent Maintenance”

| These notes document CLISP version 2.45 | Last modified: 2008-05-14

Enter your search termsSubmit search form
Webclisp.cons.orgclisp.podval.orgwww.lisp.org

Prev | Up | Next
29.1. Introduction | Home | 29.3. Classes