If an object is a direct instance of class~$C$ then the object is also an
(indirect) instance of every superclass of $C$.
-If $C$ has a proper superclass $B$, then $B$ is not allowed to have $C$ has a
-direct superclass. In different terms, if we construct a graph, whose
-vertices are classes, and draw an edge from each class to each of its direct
-superclasses, then this graph must be acyclic. In yet other terms, the `is a
-superclass of' relation is a partial order on classes.
+If $C$ has a proper superclass $B$, then $B$ must not have $C$ as a direct
+superclass. In different terms, if we construct a graph, whose vertices are
+classes, and draw an edge from each class to each of its direct superclasses,
+then this graph must be acyclic. In yet other terms, the `is a superclass
+of' relation is a partial order on classes.
\subsubsection{The class precedence list}
This partial order is not quite sufficient for our purposes. For each class
not be a direct superclass of $C$.
Superclass links must obey the following rule: if $C$ is a class, then there
-must be no three superclasses $X$, $Y$ and~$Z$ of $C$ such that $Z$ is the
-link superclass of both $X$ and $Y$. As a consequence of this rule, the
-superclasses of $C$ can be partitioned into linear \emph{chains}, such that
-superclasses $A$ and $B$ are in the same chain if and only if one can trace a
-path from $A$ to $B$ by following superclass links, or \emph{vice versa}.
+must be no three distinct superclasses $X$, $Y$ and~$Z$ of $C$ such that $Z$
+is the link superclass of both $X$ and $Y$. As a consequence of this rule,
+the superclasses of $C$ can be partitioned into linear \emph{chains}, such
+that superclasses $A$ and $B$ are in the same chain if and only if one can
+trace a path from $A$ to $B$ by following superclass links, or \emph{vice
+versa}.
Since a class links only to one of its proper superclasses, the classes in a
chain are naturally ordered from most- to least-specific. The least specific
A class object's slots contain or point to useful information, tables and
functions for working with that class's instances. (The @|SodClass| class
-doesn't define any messages, so it doesn't have any methods. In Sod, a class
-slot containing a function pointer is not at all the same thing as a method.)
+doesn't define any messages, so it doesn't have any methods other than for
+the @|SodObject| lifecycle messages @|init| and @|teardown|; see
+\xref{sec:concepts.lifecycle}. In Sod, a class slot containing a function
+pointer is not at all the same thing as a method.)
\subsubsection{Conversions}
Suppose one has a value of type pointer-to-class-type for some class~$C$, and
conversion can fail: the object in question might not be an instance of~$B$
after all. The macro \descref{SOD_CONVERT}{mac} and the function
\descref{sod_convert}{fun} perform general conversions. They return a null
- pointer if the conversion fails. (There are therefore your analogue to the
+ pointer if the conversion fails. (These are therefore your analogue to the
\Cplusplus\ @|dynamic_cast<>| operator.)
\end{itemize}
The Sod translator generates macros for performing both in-chain and
node [midway, right, align=left]
{Most to \\ least \\ specific};}
- \delgstack{a}{}{Around method}
+ \delgstack{a}{}{@|around| method}
\draw [<-] ($(a0.south)!.5!(a0.south west) - (0mm, 1mm)$) --
++(0mm, -4mm);
\draw [->] ($(a0.south)!.5!(a0.south east) - (0mm, 1mm)$) --
node [code, midway, left=3mm] {next_method}
node (b0) [method, above left = 1mm + 4mm and -6mm - 4mm] {};
\node (b1) [method] at ($(b0) - (2mm, 2mm)$) {};
- \node (bn) [method] at ($(b1) - (2mm, 2mm)$) {Before method};
+ \node (bn) [method] at ($(b1) - (2mm, 2mm)$) {@|before| method};
\draw [->, order] ($(bn.west) - (6mm, 0mm)$) -- ++(12mm, 12mm)
node [midway, above left, align=center] {Most to \\ least \\ specific};
\draw [->] ($(b0.north east) + (-10mm, 1mm)$) -- ++(8mm, 8mm)
node [action, midway, right=3mm] {return}
node (f0) [method, above right = 1mm and -6mm] {};
\node (f1) [method] at ($(f0) + (-2mm, 2mm)$) {};
- \node (fn) [method] at ($(f1) + (-2mm, 2mm)$) {After method};
+ \node (fn) [method] at ($(f1) + (-2mm, 2mm)$) {@|after| method};
\draw [<-, order] ($(f0.east) + (6mm, 0mm)$) -- ++(-12mm, 12mm)
node [midway, above right, align=center]
{Least to \\ most \\ specific};
If there any remaining @|around| methods, then @|next_method| invokes the
next most specific such method, returning whichever value that method
- returns; otherwise the behaviour of @|next_method| is to invoke the before
- methods (if any), followed by the most specific primary method, followed by
- the @|around| methods (if any), and to return whichever value was returned
- by the most specific primary method, as described in the following items.
- That is, the behaviour of the least specific @|around| method's
- @|next_method| function is exactly the behaviour that the effective method
- would have if there were no @|around| methods. Note that if the
- least-specific @|around| method calls its @|next_method| more than once
- then the whole sequence of @|before|, primary, and @|after| methods occurs
- multiple times.
+ returns; otherwise the behaviour of @|next_method| is to invoke the
+ @|before| methods (if any), followed by the most specific primary method,
+ followed by the @|after| methods (if any), and to return whichever value
+ was returned by the most specific primary method, as described in the
+ following items. That is, the behaviour of the least specific @|around|
+ method's @|next_method| function is exactly the behaviour that the
+ effective method would have if there were no @|around| methods. Note that
+ if the least-specific @|around| method calls its @|next_method| more than
+ once then the whole sequence of @|before|, primary, and @|after| methods
+ occurs multiple times.
The value returned by the most specific @|around| method is the value
returned by the effective method.
A typical use for @|around| methods is to allow a base class to set up the
dynamic environment appropriately for the primary methods of its subclasses,
-e.g., by claiming a lock, and restore it afterwards.
+e.g., by claiming a lock, and releasing it afterwards.
The @|next_method| function provided to methods with the primary and
@|around| rĂ´les accepts the same arguments, and returns the same type, as the
Once an instance's storage has been imprinted, it is technically possible to
send messages to the instance; however the instance's slots are still
-uninitialized at this point, the applicable methods are unlikely to do much
-of any use unless they've been written specifically for the purpose.
+uninitialized at this point, so the applicable methods are unlikely to do
+much of any use unless they've been written specifically for the purpose.
The following simple function imprints storage at address @<p> as an instance
of a class, given a pointer to its class object @<cls>.
Slots are initialized in a well-defined order.
\begin{itemize}
-\item Slots defined by a more specific superclasses are initialized after
- slots defined by a less specific superclass.
+\item Slots defined by a more specific superclass are initialized after slots
+ defined by a less specific superclass.
\item Slots defined by the same class are initialized in the order in which
their definitions appear.
\end{itemize}
by an explicit @|initarg| item appearing in a class definition: the item
defines a name, type, and (optionally) a default value for the initarg.
\emph{Slot initargs} are defined by attaching an @|initarg| property to a
-slot or slot initializer item: the property's determines the initarg's name,
-while the type is taken from the underlying slot type; slot initargs do not
-have default values. Both kinds define a \emph{direct initarg} for the
+slot or slot initializer item: the property's value determines the initarg's
+name, while the type is taken from the underlying slot type; slot initargs do
+not have default values. Both kinds define a \emph{direct initarg} for the
containing class.
Initargs are inherited. The \emph{applicable} direct initargs for an @|init|