% -*- Mode: TeX -*- %% Classes While the \CLOS\ is general enough to describe all \term{standardized} \term{classes} (including, for example, \typeref{number}, \typeref{hash-table}, and \typeref{symbol}), \thenextfigure\ contains a list of \term{classes} that are especially relevant to understanding the \CLOS. \DefineFigure{ObjectSystemClasses} \displaythree{Object System Classes}{ built-in-class&method-combination&standard-object\cr class&standard-class&structure-class\cr generic-function&standard-generic-function&structure-object\cr method&standard-method&\cr } \beginsubSection{Introduction to Classes} A \newterm{class} is an \term{object} that determines the structure and behavior of a set of other \term{objects}, which are called its \newtermidx{instances}{instance}. A \term{class} can inherit structure and behavior from other \term{classes}. A \term{class} whose definition refers to other \term{classes} for the purpose of inheriting from them is said to be a \term{subclass} of each of those \term{classes}. The \term{classes} that are designated for purposes of inheritance are said to be \term{superclasses} of the inheriting \term{class}. A \term{class} can have a \term{name}. The \term{function} \funref{class-name} takes a \term{class} \term{object} and returns its \term{name}. The \term{name} of an anonymous \term{class} is \nil. A \term{symbol} can \term{name} a \term{class}. The \term{function} \funref{find-class} takes a \term{symbol} and returns the \term{class} that the \term{symbol} names. A \term{class} has a \term{proper name} if the \term{name} is a \term{symbol} and if the \term{name} of the \term{class} names that \term{class}. That is, a \term{class}~$C$ has the \term{proper name}~$S$ if $S=$ \f{(class-name $C$)} and $C=$ \f{(find-class $S$)}. Notice that it is possible for \f{(find-class $S\sub 1$)} $=$ \f{(find-class $S\sub 2$)} and $S\sub 1\neq S\sub 2$. If $C=$ \f{(find-class $S$)}, we say that $C$ is the \term{class} \term{named} $S$. A \term{class} $C\sub{1}$ is a \newterm{direct superclass} of a \term{class} $C\sub{2}$ if $C\sub{2}$ explicitly designates $C\sub{1}$ as a \term{superclass} in its definition. In this case $C\sub{2}$ is a \newterm{direct subclass} of $C\sub{1}$. A \term{class} $C\sub{n}$ is a \newterm{superclass} of a \term{class} $C\sub{1}$ if there exists a series of \term{classes} $C\sub{2},\ldots,C\sub{n-1}$ such that $C\sub{i+1}$ is a \term{direct superclass} of $C\sub{i}$ for $1 \leq i "$S\sub{pie}$ per Barmar and Laubsch. The set $S\sub{pie}$~$=$ $\{${\tt pie, apple, cinnamon, fruit, spice, food, standard-object, t}$\}$. The set $R$~$=$ $\{${\tt (pie, apple), (apple, cinnamon), (apple, fruit), (cinnamon, spice), \hfil\break (fruit, food), (spice, food), (food, standard-object), (standard-object, t)}$\}$. The class \f{pie} is not preceded by anything, so it comes first; the result so far is {\tt (pie)}. Remove \f{pie} from $S$ and pairs mentioning \f{pie} from $R$ to get $S$~$=$ $\{${\tt apple, cinnamon, fruit, spice, food, standard-object, t}$\}$ and $R$~$=$~$\{${\tt (apple, cinnamon), (apple, fruit), (cinnamon, spice),\hfil\break (fruit, food), (spice, food), (food, standard-object), (standard-object, t)}$\}$. The class \f{apple} is not preceded by anything, so it is next; the result is {\tt (pie apple)}. Removing \f{apple} and the relevant pairs results in $S$~$=$ $\{${\tt cinnamon, fruit, spice, food, standard-object, t}$\}$ and $R$~$=$ $\{${\tt (cinnamon, spice), (fruit, food), (spice, food), (food, standard-object),\hfil\break (standard-object, t)}$\}$. The classes \f{cinnamon} and {\tt fruit} are not preceded by anything, so the one with a direct \term{subclass} rightmost in the \term{class precedence list} computed so far goes next. The class \f{apple} is a direct \term{subclass} of {\tt fruit}, and the class \f{pie} is a direct \term{subclass} of \f{cinnamon}. Because \f{apple} appears to the right of \f{pie} in the \term{class precedence list}, {\tt fruit} goes next, and the result so far is {\tt (pie apple fruit)}. $S$~$=$ $\{${\tt cinnamon, spice, food, standard-object, t}$\}$; $R$~$=$ $\{${\tt (cinnamon, spice), (spice, food),\hfil\break (food, standard-object), (standard-object, t)}$\}$. The class \f{cinnamon} is next, giving the result so far as {\tt (pie apple fruit cinnamon)}. At this point $S$~$=$ $\{${\tt spice, food, standard-object, t}$\}$; $R$~$=$ $\{${\tt (spice, food), (food, standard-object), (standard-object, t)}$\}$. The classes \f{spice}, \f{food}, \typeref{standard-object}, and \typeref{t} are added in that order, and the \term{class precedence list} is \f{(pie apple fruit cinnamon spice food standard-object t)}. It is possible to write a set of \term{class} definitions that cannot be ordered. For example: \code (defclass new-class (fruit apple) ()) (defclass apple (fruit) ()) \endcode The class \f{fruit} must precede \f{apple} because the local ordering of \term{superclasses} must be preserved. The class \f{apple} must precede \f{fruit} because a \term{class} always precedes its own \term{superclasses}. When this situation occurs, an error is signaled, as happens here when the system tries to compute the \term{class precedence list} %Barmar suggested we add: of \f{new-class}. The following might appear to be a conflicting set of definitions: \code (defclass pie (apple cinnamon) ()) (defclass pastry (cinnamon apple) ()) (defclass apple () ()) (defclass cinnamon () ()) \endcode The \term{class precedence list} for \f{pie} is \f{(pie apple cinnamon standard-object t)}. The \term{class precedence list} for \f{pastry} is \f{(pastry cinnamon apple standard-object t)}. It is not a problem for \f{apple} to precede \f{cinnamon} in the ordering of the \term{superclasses} of \f{pie} but not in the ordering for \f{pastry}. However, it is not possible to build a new \term{class} that has both \f{pie} and \f{pastry} as \term{superclasses}. \endsubsubsection%{Examples of Class Precedence List Determination} \endsubSection%{Determining the Class Precedence List} \beginsubSection{Redefining Classes} \DefineSection{ClassReDef} %"instance" => "direct instance" per Barrett,Barmar,Moon. A \term{class} that is a \term{direct instance} of \typeref{standard-class} can be redefined if the new \term{class} is also %"instance" => "direct instance" per Barrett,Barmar,Moon. a \term{direct instance} of \typeref{standard-class}. Redefining a \term{class} modifies the existing \term{class} \term{object} to reflect the new \term{class} definition; it does not create a new \term{class} \term{object} for the \term{class}. Any \term{method} \term{object} created by a \kwd{reader}, \kwd{writer}, or \kwd{accessor} option specified by the old \macref{defclass} form is removed from the corresponding \term{generic function}. \term{Methods} specified by the new \macref{defclass} form are added. % any function specified by the \kwd{constructor} option of the % old \macref{defclass} form is removed from the corresponding symbol function cell. When the class $C$ is redefined, changes are propagated to its \term{instances} and to \term{instances} of any of its \term{subclasses}. Updating such an \term{instance} occurs at an \term{implementation-dependent} time, but no later than the next time a \term{slot} of that \term{instance} is read or written. Updating an \term{instance} does not change its identity as defined by \thefunction{eq}. The updating process may change the \term{slots} of that particular \term{instance}, but it does not create a new \term{instance}. Whether updating an \term{instance} consumes storage is \term{implementation-dependent}. Note that redefining a \term{class} may cause \term{slots} to be added or deleted. If a \term{class} is redefined in a way that changes the set of \term{local slots} \term{accessible} in \term{instances}, the \term{instances} are updated. It is \term{implementation-dependent} whether \term{instances} are updated if a \term{class} is redefined in a way that does not change the set of \term{local slots} \term{accessible} in \term{instances}. The value of a \term{slot} that is specified as shared both in the old \term{class} and in the new \term{class} is retained. If such a \term{shared slot} was unbound in the old \term{class}, it is unbound in the new \term{class}. \term{Slots} that were local in the old \term{class} and that are shared in the new \term{class} are initialized. Newly added \term{shared slots} are initialized. Each newly added \term{shared slot} is set to the result of evaluating the %captured \kwd{initform} form \term{captured initialization form} for the \term{slot} that was specified in the \macref{defclass} \term{form} for the new \term{class}. %If there is no \kwd{initform} form, If there was no \term{initialization form}, the \term{slot} is unbound. If a \term{class} is redefined in such a way that the set of \term{local slots} \term{accessible} in an \term{instance} of the \term{class} is changed, a two-step process of updating the \term{instances} of the \term{class} takes place. The process may be explicitly started by invoking the generic function \funref{make-instances-obsolete}. This two-step process can happen in other circumstances in some implementations. For example, in some implementations this two-step process is triggered if the order of \term{slots} in storage is changed. The first step modifies the structure of the \term{instance} by adding new \term{local slots} and discarding \term{local slots} that are not defined in the new version of the \term{class}. The second step initializes the newly-added \term{local slots} and performs any other user-defined actions. These two steps are further specified in the next two sections. \beginsubsubsection{Modifying the Structure of Instances} \reviewer{Barmar: What about shared slots that are deleted?}%!!! The first step modifies the structure of \term{instances} of the redefined \term{class} to conform to its new \term{class} definition. \term{Local slots} specified by the new \term{class} definition that are not specified as either local or shared by the old \term{class} are added, and \term{slots} not specified as either local or shared by the new \term{class} definition that are specified as local by the old \term{class} are discarded. The \term{names} of these added and discarded \term{slots} are passed as arguments to \funref{update-instance-for-redefined-class} as described in the next section. The values of \term{local slots} specified by both the new and old \term{classes} are retained. If such a \term{local slot} was unbound, it remains unbound. The value of a \term{slot} that is specified as shared in the old \term{class} and as local in the new \term{class} is retained. If such a \term{shared slot} was unbound, the \term{local slot} is unbound. \endsubsubsection%{Modifying the Structure of the Instance} \beginsubsubsection{Initializing Newly Added Local Slots} The second step initializes the newly added \term{local slots} and performs any other user-defined actions. This step is implemented by the generic function \funref{update-instance-for-redefined-class}, which is called after completion of the first step of modifying the structure of the \term{instance}. The generic function \funref{update-instance-for-redefined-class} takes four required arguments: the \term{instance} being updated after it has undergone the first step, a list of the names of \term{local slots} that were added, a list of the names of \term{local slots} that were discarded, and a property list containing the \term{slot} names and values of \term{slots} that were discarded and had values. Included among the discarded \term{slots} are \term{slots} that were local in the old \term{class} and that are shared in the new \term{class}. The generic function \funref{update-instance-for-redefined-class} also takes any number of initialization arguments. When it is called by the system to update an \term{instance} whose \term{class} has been redefined, no initialization arguments are provided. There is a system-supplied primary \term{method} for \funref{update-instance-for-redefined-class} whose \term{parameter specializer} for its \term{instance} argument is \theclass{standard-object}. First this \term{method} checks the validity of initialization arguments and signals an error if an initialization argument is supplied that is not declared as valid. (For more information, \seesection\DeclaringInitargValidity.) Then it calls the generic function \funref{shared-initialize} with the following arguments: the \term{instance}, the list of \term{names} of the newly added \term{slots}, and the initialization arguments it received. \endsubsubsection%{Initializing Newly added Local Slots} \beginsubsubsection{Customizing Class Redefinition} \reviewer{Barmar: This description is hard to follow.}%!!! \term{Methods} for \funref{update-instance-for-redefined-class} may be defined to specify actions to be taken when an \term{instance} is updated. If only \term{after methods} for \funref{update-instance-for-redefined-class} are defined, they will be run after the system-supplied primary \term{method} for initialization and therefore will not interfere with the default behavior of \funref{update-instance-for-redefined-class}. Because no initialization arguments are passed to \funref{update-instance-for-redefined-class} when it is called by the system, the %\kwd{initform} forms \term{initialization forms} for \term{slots} that are filled by \term{before methods} for \funref{update-instance-for-redefined-class} will not be evaluated by \funref{shared-initialize}. \term{Methods} for \funref{shared-initialize} may be defined to customize \term{class} redefinition. For more information, \seesection\SharedInitialize. \endsubsubsection%{Customizing Class Redefinition} %% The following was removed by request of Symbolics, who point out that other %% extensions may well be permitted too, and there's no reason to give special %% advertising to these. -kmp 9-Oct-90 % % \beginsubsubsection{Extensions} % % There are two allowed extensions to \term{class} redefinition: % % \beginlist % % \itemitem{\bull} The \OS\ may be extended to permit the new \term{class} % to be an \term{instance} of a \term{metaclass} % other than the \term{metaclass} of the % old \term{class}. % % \itemitem{\bull} The \OS\ may be extended to support an updating process % when either the old or the new \term{class} is an \term{instance} of a % \term{class} % other than \typeref{standard-class} that is not a \term{built-in class}. % % \endlist % % \endsubsubsection%{Extensions} \beginsubSection{Integrating Types and Classes} \DefineSection{IntegratingTypesAndClasses} The \CLOS\ maps the space of \term{classes} into the space of \term{types}. Every \term{class} that has a proper name has a corresponding \term{type} with the same \term{name}. The proper name of every \term{class} is a valid \term{type specifier}. In addition, every \term{class} \term{object} is a valid \term{type specifier}. Thus the expression \f{(typep \param{object} \param{class})} evaluates to \term{true} if the \term{class} of \param{object} is \param{class} itself or a \term{subclass} of \term{class}. The evaluation of the expression \f{(subtypep class1 class2)} returns the values %was {\tt t~t} but came out as "t~t" in formatted form. -kmp 10-Oct-90 %\t~\t\ if \f{class1} is a subclass of \f{class2} or if they are the \term{true} and \term{true} if \f{class1} is a subclass of \f{class2} or if they are the same \term{class}; otherwise it returns the values %was {\tt nil~t} %\nil~\t. \term{false} and \term{true}. % If $I$ is an \term{instance} of some \term{class} % $C$ named $S$ and $C$ is an \term{instance} of \typeref{standard-class}, % the evaluation of the expression \f{(type-of $I$\/)} will return $S$ if % $S$ is the proper name of $C$\negthinspace; if $S$ is not the proper % name of $C$\negthinspace, the expression \f{(type-of $I$\/)} will % return $C$\negthinspace. %% Barmar thought the above was too complicated. %% This is a partial simplification, not quite what he wanted, but hopefully %% an improvement. If $I$ is an \term{instance} of some \term{class} $C$ named $S$ and $C$ is an \term{instance} of \typeref{standard-class}, the evaluation of the expression \f{(type-of $I$\/)} returns $S$ if $S$ is the \term{proper name} of $C$; otherwise, it returns $C$. Because the names of \term{classes} and \term{class} \term{objects} are \term{type specifiers}, they may be used in the special form \specref{the} and in type declarations. Many but not all of the predefined \term{type specifiers} have a corresponding \term{class} with the same proper name as the \term{type}. These type specifiers are listed in \figref\ClassTypeCorrespondence. For example, \thetype{array} has a corresponding \term{class} named \typeref{array}. No \term{type specifier} that is a list, such as {\tt (vector double-float 100)}, has a corresponding \term{class}. The \term{operator} \macref{deftype} does not create any \term{classes}. Each \term{class} that corresponds to a predefined \term{type specifier} can be implemented in one of three ways, at the discretion of each implementation. It can be a \term{standard class}, %% Not necessary. -kmp 12-Feb-92 % (of the kind defined by \macref{defclass}), a \term{structure class}, %% Not necessary. -kmp 12-Feb-92 % (defined by \macref{defstruct}), \issue{METACLASS-OF-SYSTEM-CLASS:UNSPECIFIED} %or a \term{built-in class}. or a \term{system class}. \endissue{METACLASS-OF-SYSTEM-CLASS:UNSPECIFIED} %% Not necessary. -kmp 12-Feb-92 % (implemented in a special, non-extensible way). %"instances" => "generalized instances" per Barmar,Moon. A \term{built-in class} is one whose \term{generalized instances} have restricted capabilities or special representations. Attempting to use \macref{defclass} to define \term{subclasses} of a \typeref{built-in-class} signals an error. %"instance" => "generalized instance" per Barmar,Moon. Calling \funref{make-instance} to create a \term{generalized instance} of a \term{built-in class} signals an error. Calling \funref{slot-value} on a %"instance" => "generalized instance" per Barmar,Moon. \term{generalized instance} of a \term{built-in class} signals an error. Redefining a \term{built-in class} or using \funref{change-class} to change %"instance" => "object" per Barmar,Moon. the \term{class} of an \term{object} to or from a \term{built-in class} signals an error. However, \term{built-in classes} can be used as \term{parameter specializers} in \term{methods}. %The \OS\ specifies that all predefined \term{type specifiers} %listed in \figref\ClassTypeCorrespondence\ are built-in classes, but a particular %implementation is allowed to extend the \OS\ to define some of them as %standard classes or as structure classes. It is possible to determine whether a \term{class} is a \term{built-in class} by checking the \term{metaclass}. A \term{standard class} is an \term{instance} of \theclass{standard-class}, a \term{built-in class} is an \term{instance} of \theclass{built-in-class}, and a \term{structure class} is an \term{instance} of \theclass{structure-class}. Each \term{structure} \term{type} created by \macref{defstruct} without using the \kwd{type} option has a corresponding \term{class}. %"instance" => "generalized instance" per Barmar,Moon. This \term{class} is a \term{generalized instance} of \theclass{structure-class}. %A portable program must assume that %\typeref{structure-class} is a subclass of \typeref{built-in-class} and has the %same restrictions as built-in classes. Whether \theclass{structure-class} %in fact is a subclass of \typeref{built-in-class} is %\term{implementation-dependent}. The \kwd{include} option of \macref{defstruct} creates a direct \term{subclass} of the \term{class} that corresponds to the included \term{structure} %Added "type" -kmp \term{type}. % I moved the following two paragraphs here from the dictionary entry % for CLASS. --sjl 7 Mar 92 \issue{CONDITION-SLOTS:HIDDEN} It is \term{implementation-dependent} whether \term{slots} are involved in the operation of \term{functions} defined in this specification on \term{instances} of \term{classes} defined in this specification, except when \term{slots} are explicitly defined by this specification. If in a particular \term{implementation} a \term{class} defined in this specification has \term{slots} that are not defined by this specfication, the names of these \term{slots} must not be \term{external symbols} of \term{packages} defined in this specification nor otherwise \term{accessible} in \thepackage{cl-user}. \endissue{CONDITION-SLOTS:HIDDEN} The purpose of specifying that many of the standard \term{type specifiers} have a corresponding \term{class} is to enable users to write \term{methods} that discriminate on these \term{types}. \term{Method} selection requires that a \term{class precedence list} can be determined for each \term{class}. The hierarchical relationships among the \term{type specifiers} are mirrored by relationships among the \term{classes} corresponding to those \term{types}. %The existing type hierarchy is used for determining the %\term{class precedence list} %for each \term{class} that corresponds to a predefined %\term{type}. In some cases, %a \term{local precedence order} is not specifiied for two \term{supertypes} %of a %given \term{type specifier}. For example, \typeref{null} is a \term{subtype} %of both \typeref{symbol} and \typeref{list}, but it is not specified %whether \typeref{symbol} is more specific or less %specific than \typeref{list}. The \CLOS\ defines those %relationships for all such \term{classes}. \figref\ClassTypeCorrespondence\ lists the set of \term{classes} that correspond to predefined \term{type specifiers}. \issue{REAL-NUMBER-TYPE:X3J13-MAR-89} \DefineFigure{ClassTypeCorrespondence} \displaythree{Classes that correspond to pre-defined type specifiers}{ arithmetic-error&generic-function&simple-error\cr array&hash-table&simple-type-error\cr bit-vector&integer&simple-warning\cr broadcast-stream&list&standard-class\cr built-in-class&logical-pathname&standard-generic-function\cr cell-error&method&standard-method\cr character&method-combination&standard-object\cr class&null&storage-condition\cr complex&number&stream\cr concatenated-stream&package&stream-error\cr condition&package-error&string\cr cons&parse-error&string-stream\cr control-error&pathname&structure-class\cr division-by-zero&print-not-readable&structure-object\cr echo-stream&program-error&style-warning\cr end-of-file&random-state&symbol\cr error&ratio&synonym-stream\cr file-error&rational&t\cr file-stream&reader-error&two-way-stream\cr float&readtable&type-error\cr floating-point-inexact&real&unbound-slot\cr floating-point-invalid-operation&restart&unbound-variable\cr floating-point-overflow&sequence&undefined-function\cr floating-point-underflow&serious-condition&vector\cr function&simple-condition&warning\cr } \endissue{REAL-NUMBER-TYPE:X3J13-MAR-89} The \term{class precedence list} information specified in the entries for each of these \term{classes} are those that are required by the \OS. Individual implementations may be extended to define other type specifiers to have a corresponding \term{class}. Individual implementations may be extended to add other \term{subclass} relationships and to add other \term{elements} to the \term{class precedence lists} as long as they do not violate the type relationships and disjointness requirements specified by this standard. A standard \term{class} defined with no direct \term{superclasses} is guaranteed to be disjoint from all of the \term{classes} in the table, except for the class named \typeref{t}. \endsubSection%{Integrating Types and Classes}