Common Lisp the Language, 2nd Edition

Next: Determining the Class Up: Programmer Interface Concepts Previous: Examples

## 28.1.4. Integrating Types and Classes

The Common Lisp Object System maps the space of classes into the Common Lisp type space. Every class that has a proper name has a corresponding type with the same name.

The proper name of every class is a valid type specifier. In addition, every class object is a valid type specifier. Thus the expression `(typep object class)` evaluates to true if the class of object is class itself or a subclass of class. The evaluation of the expression `(subtypep class1 class2)` returns the values `t` and `t` if class1 is a subclass of class2 or if they are the same class; otherwise it returns the values `nil` and `t`. If I is an instance of some class C named S and C is an instance of `standard-class`, the evaluation of the expression `(type-of I)` will return S if S is the proper name of C; if S is not the proper name of C, the expression `(type-of I)` will return C.

Because the names of classes and class objects are type specifiers, they may be used in the special form `the` and in type declarations.

Many but not all of the predefined Common Lisp type specifiers have a corresponding class with the same proper name as the type. These type specifiers are listed in table 28-1. For example, the type `array` has a corresponding class named `array`. No type specifier that is a list, such as `(vector double-float 100)`, has a corresponding class. The form `deftype` does not create any classes.

Each class that corresponds to a predefined Common Lisp type specifier can be implemented in one of three ways, at the discretion of each implementation. It can be a standard class (of the kind defined by `defclass`), a structure class (defined by `defstruct`), or a built-in class (implemented in a special, non-extensible way).

A built-in class is one whose instances have restricted capabilities or special representations. Attempting to use `defclass` to define subclasses of a built-in class signals an error. Calling `make-instance` to create an instance of a built-in class signals an error. Calling `slot-value` on an instance of a built-in class signals an error. Redefining a built-in class or using `change-class` to change the class of an instance to or from a built-in class signals an error. However, built-in classes can be used as parameter specializers in methods.

It is possible to determine whether a class is a built-in class by checking the metaclass. A standard class is an instance of `standard-class`, a built-in class is an instance of `built-in-class`, and a structure class is an instance of `structure-class`.

Each structure type created by `defstruct` without using the `:type` option has a corresponding class. This class is an instance of `structure-class`.

The `:include` option of `defstruct` creates a direct subclass of the class that corresponds to the included structure.

The purpose of specifying that many of the standard Common Lisp type specifiers have a corresponding class is to enable users to write methods that discriminate on these types. Method selection requires that a class precedence list can be determined for each class.

The hierarchical relationships among the Common Lisp type specifiers are mirrored by relationships among the classes corresponding to those types. The existing type hierarchy is used for determining the class precedence list for each class that corresponds to a predefined Common Lisp type. In some cases, the first edition did not specify a local precedence order for two supertypes of a given type specifier. For example, `null` is a subtype of both `symbol` and `list`, but the first edition did not specify whether `symbol` is more specific or less specific than `list`. The CLOS specification defines those relationships for all such classes.

Table 28-1 lists the set of classes required by the Object System that correspond to predefined Common Lisp type specifiers. The superclasses of each such class are presented in order from most specific to most general, thereby defining the class precedence list for the class. The local precedence order for each class that corresponds to a Common Lisp type specifier can be derived from this table.

Individual implementations may be extended to define other type specifiers to have a corresponding class. Individual implementations can be extended to add other subclass relationships and to add other elements to the class precedence lists in the above table as long as they do not violate the type relationships and disjointness requirements specified in section 2.15. A standard class defined with no direct superclasses is guaranteed to be disjoint from all of the classes in the table, except for the class named `t`.

[At this point the original CLOS report specified that certain Common Lisp types were to appear in table 28-1 if and only if X3J13 voted to make them disjoint from `cons`, `symbol`, `array`, `number`, and `character`. X3J13 voted to do so in June 1988 (DATA-TYPES-HIERARCHY-UNDERSPECIFIED) . I have added these types and their class precedence lists to the table; the new types are indicated by asterisks.-GLS]

    ----------------------------------------------------------------
    Table 28-1: Class Precedence Lists for Predefined Types

    Predefined              Class Precedence List
    Common Lisp Type        for Corresponding Class
    ==============================================================
    array                   (array t)
    bit-vector              (bit-vector vector array sequence t)
    character               (character t)
    complex                 (complex number t)
    cons                    (cons list sequence t)
    float                   (float number t)
    function *              (function t)
    hash-table *            (hash-table t)
    integer                 (integer rational number t)
    list                    (list sequence t)
    null                    (null symbol list sequence t)
    number                  (number t)
    package *               (package t)
    pathname *              (pathname t)
    random-state *          (random-state t)
    ratio                   (ratio rational number t)
    rational                (rational number t)
    readtable *             (readtable t)
    sequence                (sequence t)
    stream *                (stream t)
    string                  (string vector array sequence t)
    symbol                  (symbol t)
    t                       (t)
    vector                  (vector array sequence t)
    ==============================================================

    [An asterisk indicates a type added to this table as a consequence of
    a portion of the CLOS specification that was conditional on X3J13
    voting to make that type disjoint from certain other built-in types
    (DATA-TYPES-HIERARCHY-UNDERSPECIFIED).---GLS]

    ----------------------------------------------------------------

Next: Determining the Class Up: Programmer Interface Concepts Previous: Examples