The following simple function correctly allocates and returns space for an
instance of a class given a pointer to its class object @<cls>.
\begin{prog}
- void *allocate_instance(const SodClass *cls) \\ \ind
+ void *allocate_instance(const SodClass *cls) \\ \ind
\{ return malloc(cls@->cls.initsz); \}
\end{prog}
The following simple function imprints storage at address @<p> as an instance
of a class, given a pointer to its class object @<cls>.
\begin{prog}
- void imprint_instance(const SodClass *cls, void *p) \\ \ind
+ void imprint_instance(const SodClass *cls, void *p) \\ \ind
\{ cls@->cls.imprint(p); \}
\end{prog}
message, defined by the @|SodObject| class. This message uses a nonstandard
method combination which works like the standard combination, except that the
\emph{default behaviour}, if there is no overriding method, is to initialize
-the instance's slots using the initializers defined in the class and its
-superclasses, and to invoke each superclass's initialization fragments. This
-default behaviour may be invoked multiple times if some method calls on its
-@|next_method| more than once, unless some other method takes steps to
-prevent this.
+the instance's slots, as described below, and to invoke each superclass's
+initialization fragments. This default behaviour may be invoked multiple
+times if some method calls on its @|next_method| more than once, unless some
+other method takes steps to prevent this.
Slots are initialized in a well-defined order.
\begin{itemize}
or @|goto| for special control-flow effects, but this is not likely to be a
good idea.
-Note that an initialization fragment defined in a class is copied literally
-into each subclass's initialization method. This is fine for simple cases
-but wasteful if the initialization logic is complicated. More complex
-initialization behaviour should be added either by having an initialization
-fragments call functions (necessarily with external linkage), or by defining
-@|after| methods on the @|init| message. These will be run after the slot
-initializers have been applied, in reverse precedence order.
-
-Initialization is \emph{parametrized}, so the caller may select from a space
-of possible initial states for the new instance, or to inform the new
-instance about some other objects known to the caller. Specifically, the
-@|init| message accepts keyword arguments (\xref{sec:concepts.keywords})
-which can be defined and used by methods defined on it.
+The @|init| message accepts keyword arguments
+(\xref{sec:concepts.methods.keywords}). The set of acceptable keywords is
+determined by the applicable methods as usual, but also by the
+\emph{initargs} defined by the receiving instance's class and its
+superclasses, which are made available to slot initializers and
+initialization fragments.
+
+There are two kinds of initarg definitions. \emph{User initargs} are defined
+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
+containing class.
+
+Initargs are inherited. The \emph{applicable} direct initargs for an @|init|
+effective method are those defined by the receiving object's class, and all
+of its superclasses. Applicable direct initargs with the same name are
+merged to form \emph{effective initargs}. An error is reported if two
+applicable direct initargs have the same name but different types. The
+default value of an effective initarg is taken from the most specific
+applicable direct initarg which specifies a defalt value; if no applicable
+direct initarg specifies a default value then the effective initarg has no
+default.
+
+All initarg values are made available at runtime to user code --
+initialization fragments and slot initializer expressions -- through local
+variables and a @|suppliedp| structure, as in a direct method
+(\xref{sec:concepts.methods.keywords}). Furthermore, slot initarg
+definitions influence the initialization of slots.
+
+The process for deciding how to initialize a particular slot works as
+follows.
+\begin{enumerate}
+\item If there are any slot initargs defined on the slot, or any of its slot
+ initializers, \emph{and} the sender supplied a value for one or more of the
+ corresponding effective initargs, then the value of the most specific slot
+ initarg is stored in the slot.
+\item Otherwise, if there are any slot initializers defined which include an
+ initializer expression, then the initializer expression from the most
+ specific such slot initializer is evaluated and its value stored in the
+ slot.
+\item Otherwise, the slot is left uninitialized.
+\end{enumerate}
+Note that the default values (if any) of effective initargs do \emph{not}
+affect this procedure.
\subsection{Destruction}
This simple protocol can be used, for example, to implement a reference
counting system, as follows.
\begin{prog}
- [nick = ref] \\
- class ReferenceCountedObject \{ \\ \ind
- unsigned nref = 1; \\-
- void inc() \{ me@->ref.nref++; \} \\-
- [role = around] \\
- int obj.teardown() \\
- \{ \\ \ind
- if (--\,--me@->ref.nref) return (1); \\
- else return (CALL_NEXT_METHOD); \- \\
- \} \- \\
+ [nick = ref] \\
+ class ReferenceCountedObject \{ \\ \ind
+ unsigned nref = 1; \\-
+ void inc() \{ me@->ref.nref++; \} \\-
+ [role = around] \\
+ int obj.teardown() \\
+ \{ \\ \ind
+ if (--\,--me@->ref.nref) return (1); \\
+ else return (CALL_NEXT_METHOD); \-\\
+ \} \-\\
\}
\end{prog}