TclOO Package

Artifact [e469353684]
Login

Artifact e46935368410d8829c8fb26f5bf5542e9a5ad03f:

Wiki page [Doc: oo::define] by dkf 2016-09-17 11:03:35.
D 2016-09-17T11:03:35.065
L Doc:\soo::define
N text/x-markdown
U dkf
W 22518
<h1>oo::define and oo::objdefine</h1>
<DL style="font-size:.85em">
<DD><A HREF="#M2" NAME="L327">NAME</A>
<DL><DD>oo::define, oo::objdefine &mdash; define and configure classes and objects</DD></DL>
<DD><A HREF="#M3" NAME="L328">SYNOPSIS</A>
<DL>
</DL>
<DD><A HREF="#M4" NAME="L329">DESCRIPTION</A>
<DD><A HREF="#M5" NAME="L330">CONFIGURING CLASSES</A>
<DL class="configuring classes">
<DD><A HREF="#M6" NAME="L331"><B>constructor</B><I> argList bodyScript</I></A>
<DD><A HREF="#M7" NAME="L332"><B>deletemethod</B><I> name</I> ?<I>name ...</I></A>
<DD><A HREF="#M8" NAME="L333"><B>destructor</B><I> bodyScript</I></A>
<DD><A HREF="#M9" NAME="L334"><B>export</B><I> name </I>?<I>name ...</I>?</A>
<DD><A HREF="#M10" NAME="L335"><B>filter</B> ?<I>-slotOperation</I>? ?<I>methodName ...</I>?</A>
<DD><A HREF="#M11" NAME="L336"><B>forward</B><I> name cmdName </I>?<I>arg ...</I>?</A>
<DD><A HREF="#M12" NAME="L337"><B>method</B><I> name argList bodyScript</I></A>
<DD><A HREF="#M13" NAME="L338"><B>mixin</B> ?<I>-slotOperation</I>? ?<I>className ...</I>?</A>
<DD><A HREF="#M14" NAME="L339"><B>renamemethod</B><I> fromName toName</I></A>
<DD><A HREF="#M15" NAME="L340"><B>self</B><I> subcommand arg ...</I></A>
<DD><A HREF="#M16" NAME="L341"><B>self</B><I> script</I></A>
<DD><A HREF="#M17" NAME="L342"><B>superclass</B> ?<I>-slotOperation</I>? ?<I>className ...</I>?</A>
<DD><A HREF="#M18" NAME="L343"><B>unexport</B><I> name </I>?<I>name ...</I>?</A>
<DD><A HREF="#M19" NAME="L344"><B>variable</B> ?<I>-slotOperation</I>? ?<I>name ...</I>?</A>
</DL>
<DD><A HREF="#M20" NAME="L345">CONFIGURING OBJECTS</A>
<DL class="configuring objects">
<DD><A HREF="#M21" NAME="L346"><B>class</B><I> className</I></A>
<DD><A HREF="#M22" NAME="L347"><B>deletemethod</B><I> name</I> ?<I>name ...</I></A>
<DD><A HREF="#M23" NAME="L348"><B>export</B><I> name </I>?<I>name ...</I>?</A>
<DD><A HREF="#M24" NAME="L349"><B>filter</B> ?<I>-slotOperation</I>? ?<I>methodName ...</I>?</A>
<DD><A HREF="#M25" NAME="L350"><B>forward</B><I> name cmdName </I>?<I>arg ...</I>?</A>
<DD><A HREF="#M26" NAME="L351"><B>method</B><I> name argList bodyScript</I></A>
<DD><A HREF="#M27" NAME="L352"><B>mixin</B> ?<I>-slotOperation</I>? ?<I>className ...</I>?</A>
<DD><A HREF="#M28" NAME="L353"><B>renamemethod</B><I> fromName toName</I></A>
<DD><A HREF="#M29" NAME="L354"><B>unexport</B><I> name </I>?<I>name ...</I>?</A>
<DD><A HREF="#M30" NAME="L355"><B>variable</B> ?<I>-slotOperation</I>? ?<I>name ...</I>?</A>
</DL>
<DD><A HREF="#M31" NAME="L356">SLOTTED DEFINITIONS</A>
<DL class="slotted definitions">
<DD><A HREF="#M32" NAME="L357"><I>slot</I> <B>-append</B> ?<I>member ...</I>?</A>
<DD><A HREF="#M33" NAME="L358"><I>slot</I> <B>-clear</B></A>
<DD><A HREF="#M34" NAME="L359"><I>slot</I> <B>-set</B> ?<I>member ...</I>?</A>
</DL>
<DD><A HREF="#M35" NAME="L360">SLOT IMPLEMENTATION</A>
<DL class="slot implementation">
<DD><A HREF="#M36" NAME="L361"><I>slot</I> <B>Get</B></A>
<DD><A HREF="#M37" NAME="L362"><I>slot</I> <B>Set </B><I>elementList</I></A>
</DL>
<DD><A HREF="#M38" NAME="L363">EXAMPLES</A>
<DD><A HREF="#M39" NAME="L364">SEE ALSO</A>
<DD><A HREF="#M40" NAME="L365">KEYWORDS</A>
</DL>
<H3><A NAME="M2">NAME</A></H3>
<b>oo::define</b>, <b>oo::objdefine</b> &mdash; define and configure classes and objects
<H3><A NAME="M3">SYNOPSIS</A></H3>
package require TclOO<BR>
<BR>
<B>oo::define</B><I> class defScript</I><BR>
<B>oo::define</B><I> class subcommand arg</I> ?<I>arg ...</I>?<BR>
<B>oo::objdefine</B><I> object defScript</I><BR>
<B>oo::objdefine</B><I> object subcommand arg</I> ?<I>arg ...</I>?<BR>
<H3><A NAME="M4">DESCRIPTION</A></H3>
The <B>oo::define</B> command is used to control the configuration of classes,
and the <B>oo::objdefine</B> command is used to control the configuration of
objects (including classes as instance objects), with the configuration being
applied to the entity named in the <I>class</I> or the <I>object</I> argument.
Configuring a class also updates the
configuration of all subclasses of the class and all objects that are
instances of that class or which mix it in (as modified by any per-instance
configuration). The way in which the configuration is done is controlled by
either the <I>defScript</I> argument or by the <I>subcommand</I> and following
<I>arg</I> arguments; when the second is present, it is exactly as if all the
arguments from <I>subcommand</I> onwards are made into a list and that list is
used as the <I>defScript</I> argument.
<H4><A NAME="M5">CONFIGURING CLASSES</A></H4>
The following commands are supported in the <I>defScript</I> for
<B>oo::define</B>, each of which may also be used in the <I>subcommand</I> form:
<P>
<DL class="configuring classes">
<DT><A NAME="M6"><B>constructor</B><I> argList bodyScript</I></A><DD>
This creates or updates the constructor for a class. The formal arguments to
the constructor (defined using the same format as for the Tcl <B>proc</B>
command) will be <I>argList</I>, and the body of the constructor will be
<I>bodyScript</I>. When the body of the constructor is evaluated, the current
namespace of the constructor will be a namespace that is unique to the object
being constructed. Within the constructor, the <B><A HREF="?name=Doc:+next">next</A></B> command should be
used to call the superclasses' constructors. If <I>bodyScript</I> is the empty
string, the constructor will be deleted.
<P><DT><A NAME="M7"><B>deletemethod</B><I> name</I> ?<I>name ...</I></A><DD>
This deletes each of the methods called <I>name</I> from a class. The methods
must have previously existed in that class. Does not affect the superclasses
of the class, nor does it affect the subclasses or instances of the class
(except when they have a call chain through the class being modified).
<P><DT><A NAME="M8"><B>destructor</B><I> bodyScript</I></A><DD>
This creates or updates the destructor for a class. Destructors take no
arguments, and the body of the destructor will be <I>bodyScript</I>. The
destructor is called when objects of the class are deleted, and when called
will have the object's unique namespace as the current namespace. Destructors
should use the <B><A HREF="?name=Doc:+next">next</A></B> command to call the superclasses' destructors. Note
that destructors are not called in all situations (e.g. if the interpreter is
destroyed). If <I>bodyScript</I> is the empty string, the destructor will be
deleted.
<DL><DD>
Note that errors during the evaluation of a destructor <I>are not returned</I>
to the code that causes the destruction of an object. Instead, they are passed
to the currently-defined <B>bgerror</B> handler.
</DL>
<P><DT><A NAME="M9"><B>export</B><I> name </I>?<I>name ...</I>?</A><DD>
This arranges for each of the named methods, <I>name</I>, to be exported
(i.e. usable outside an instance through the instance object's command) by the
class being defined. Note that the methods themselves may be actually defined
by a superclass; subclass exports override superclass visibility, and may in
turn be overridden by instances.
<P><DT><A NAME="M10"><B>filter</B> ?<I>-slotOperation</I>? ?<I>methodName ...</I>?</A><DD>
This slot (see <B><A HREF="#M31">SLOTTED DEFINITIONS</A></B> below)
sets or updates the list of method names that are used to guard whether
method call to instances of the class may be called and what the method's
results are. Each <I>methodName</I> names a single filtering method (which may
be exposed or not exposed); it is not an error for a non-existent method to be
named since they may be defined by subclasses.
By default, this slot works by appending.
<P><DT><A NAME="M11"><B>forward</B><I> name cmdName </I>?<I>arg ...</I>?</A><DD>
This creates or updates a forwarded method called <I>name</I>. The method is
defined be forwarded to the command called <I>cmdName</I>, with additional
arguments, <I>arg</I> etc., added before those arguments specified by the
caller of the method. The <I>cmdName</I> will always be resolved using the
rules of the invoking objects' namespaces, i.e., when <I>cmdName</I> is not
fully-qualified, the command will be searched for in each object's namespace,
using the instances' namespace's path, or by looking in the global namespace.
The method will be exported if <I>name</I> starts with a lower-case letter, and
non-exported otherwise.
<P><DT><A NAME="M12"><B>method</B><I> name argList bodyScript</I></A><DD>
This creates or updates a method that is implemented as a procedure-like
script. The name of the method is <I>name</I>, the formal arguments to the
method (defined using the same format as for the Tcl <B>proc</B> command) will
be <I>argList</I>, and the body of the method will be <I>bodyScript</I>. When
the body of the method is evaluated, the current namespace of the method will
be a namespace that is unique to the current object. The method will be
exported if <I>name</I> starts with a lower-case letter, and non-exported
otherwise; this behavior can be overridden via <B>export</B> and
<B>unexport</B>.
<P><DT><A NAME="M13"><B>mixin</B> ?<I>-slotOperation</I>? ?<I>className ...</I>?</A><DD>
This slot (see <B><A HREF="#M31">SLOTTED DEFINITIONS</A></B> below)
sets or updates the list of additional classes that are to be mixed into
all the instances of the class being defined. Each <I>className</I> argument
names a single class that is to be mixed in.
By default, this slot works by replacement.
<P><DT><A NAME="M14"><B>renamemethod</B><I> fromName toName</I></A><DD>
This renames the method called <I>fromName</I> in a class to <I>toName</I>. The
method must have previously existed in the class, and <I>toName</I> must not
previously refer to a method in that class. Does not affect the superclasses
of the class, nor does it affect the subclasses or instances of the class
(except when they have a call chain through the class being modified). Does
not change the export status of the method; if it was exported before, it will
be afterwards.
<P><DT><A NAME="M15"><B>self</B><I> subcommand arg ...</I></A><DD>
<P><DT><A NAME="M16"><B>self</B><I> script</I></A><DD>
This command is equivalent to calling <B>oo::objdefine</B> on the class being
defined (see <B><A HREF="#M20">CONFIGURING OBJECTS</A></B> below for a description of the
supported values of <I>subcommand</I>). It follows the same general pattern of
argument handling as the <B>oo::define</B> and <B>oo::objdefine</B> commands,
and
&#8220;<B>oo::define </B><I>cls </I><B><A HREF="?name=Doc:+self">self </A></B><I>subcommand ...</I>&#8221;
operates identically to
&#8220;<B>oo::objdefine </B><I>cls subcommand ...</I>&#8221;.
<P><DT><A NAME="M17"><B>superclass</B> ?<I>-slotOperation</I>? ?<I>className ...</I>?</A><DD>
This slot (see <B><A HREF="#M31">SLOTTED DEFINITIONS</A></B> below)
allows the alteration of the superclasses of the class being defined.
Each <I>className</I> argument names one class that is to be a superclass of
the defined class. Note that objects must not be changed from being classes to
being non-classes or vice-versa, that an empty parent class is equivalent to
<B><A HREF="?name=Doc:+oo::object">oo::object</A></B>, and that the parent classes of <B><A HREF="?name=Doc:+oo::object">oo::object</A></B> and
<B><A HREF="?name=Doc:+oo::class">oo::class</A></B> may not be modified.
By default, this slot works by replacement.
<P><DT><A NAME="M18"><B>unexport</B><I> name </I>?<I>name ...</I>?</A><DD>
This arranges for each of the named methods, <I>name</I>, to be not exported
(i.e. not usable outside the instance through the instance object's command,
but instead just through the <B><A HREF="?name=Doc:+my">my</A></B> command visible in each object's
context) by the class being defined. Note that the methods themselves may be
actually defined by a superclass; subclass unexports override superclass
visibility, and may be overridden by instance unexports.
<P><DT><A NAME="M19"><B>variable</B> ?<I>-slotOperation</I>? ?<I>name ...</I>?</A><DD>
This slot (see <B><A HREF="#M31">SLOTTED DEFINITIONS</A></B> below) arranges for each of the named
variables to be automatically made
available in the methods, constructor and destructor declared by the class
being defined. Each variable name must not have any namespace
separators and must not look like an array access. All variables will be
actually present in the instance object on which the method is executed. Note
that the variable lists declared by a superclass or subclass are completely
disjoint, as are variable lists declared by instances; the list of variable
names is just for methods (and constructors and destructors) declared by this
class. By default, this slot works by appending.
<P></DL>
<H4><A NAME="M20">CONFIGURING OBJECTS</A></H4>
The following commands are supported in the <I>defScript</I> for
<B>oo::objdefine</B>, each of which may also be used in the <I>subcommand</I>
form:
<P>
<DL class="configuring objects">
<DT><A NAME="M21"><B>class</B><I> className</I></A><DD>
This allows the class of an object to be changed after creation. Note that the
class's constructors are not called when this is done, and so the object may
well be in an inconsistent state unless additional configuration work is done.
<P><DT><A NAME="M22"><B>deletemethod</B><I> name</I> ?<I>name ...</I></A><DD>
This deletes each of the methods called <I>name</I> from an object. The methods
must have previously existed in that object. Does not affect the classes that
the object is an instance of.
<P><DT><A NAME="M23"><B>export</B><I> name </I>?<I>name ...</I>?</A><DD>
This arranges for each of the named methods, <I>name</I>, to be exported
(i.e. usable outside the object through the object's command) by the object
being defined. Note that the methods themselves may be actually defined by a
class or superclass; object exports override class visibility.
<P><DT><A NAME="M24"><B>filter</B> ?<I>-slotOperation</I>? ?<I>methodName ...</I>?</A><DD>
This slot (see <B><A HREF="#M31">SLOTTED DEFINITIONS</A></B> below)
sets or updates the list of method names that are used to guard whether a
method call to the object may be called and what the method's results are.
Each <I>methodName</I> names a single filtering method (which may be exposed or
not exposed); it is not an error for a non-existent method to be named. Note
that the actual list of filters also depends on the filters set upon any
classes that the object is an instance of.
By default, this slot works by appending.
<P><DT><A NAME="M25"><B>forward</B><I> name cmdName </I>?<I>arg ...</I>?</A><DD>
This creates or updates a forwarded object method called <I>name</I>. The
method is defined be forwarded to the command called <I>cmdName</I>, with
additional arguments, <I>arg</I> etc., added before those arguments specified
by the caller of the method. Forwarded methods should be deleted using the
<B>method</B> subcommand. The method will be exported if <I>name</I> starts with
a lower-case letter, and non-exported otherwise.
<P><DT><A NAME="M26"><B>method</B><I> name argList bodyScript</I></A><DD>
This creates, updates or deletes an object method. The name of the method is
<I>name</I>, the formal arguments to the method (defined using the same format
as for the Tcl <B>proc</B> command) will be <I>argList</I>, and the body of the
method will be <I>bodyScript</I>. When the body of the method is evaluated, the
current namespace of the method will be a namespace that is unique to the
object. The method will be exported if <I>name</I> starts with a lower-case
letter, and non-exported otherwise.
<P><DT><A NAME="M27"><B>mixin</B> ?<I>-slotOperation</I>? ?<I>className ...</I>?</A><DD>
This slot (see <B><A HREF="#M31">SLOTTED DEFINITIONS</A></B> below)
sets or updates a per-object list of additional classes that are to be
mixed into the object. Each argument, <I>className</I>, names a single class
that is to be mixed in.
By default, this slot works by replacement.
<P><DT><A NAME="M28"><B>renamemethod</B><I> fromName toName</I></A><DD>
This renames the method called <I>fromName</I> in an object to <I>toName</I>.
The method must have previously existed in the object, and <I>toName</I> must
not previously refer to a method in that object. Does not affect the classes
that the object is an instance of. Does not change the export status of the
method; if it was exported before, it will be afterwards.
<P><DT><A NAME="M29"><B>unexport</B><I> name </I>?<I>name ...</I>?</A><DD>
This arranges for each of the named methods, <I>name</I>, to be not exported
(i.e. not usable outside the object through the object's command, but instead
just through the <B><A HREF="?name=Doc:+my">my</A></B> command visible in the object's context) by the
object being defined. Note that the methods themselves may be actually defined
by a class; instance unexports override class visibility.
<P><DT><A NAME="M30"><B>variable</B> ?<I>-slotOperation</I>? ?<I>name ...</I>?</A><DD>
This slot (see <B><A HREF="#M31">SLOTTED DEFINITIONS</A></B> below) arranges for each of the named
variables to be automatically made available in the methods declared by the
object being defined.  Each variable name must not have any namespace
separators and must not look like an array access. All variables will be
actually present in the object on which the method is executed. Note that the
variable lists declared by the classes and mixins of which the object is an
instance are completely disjoint; the list of variable names is just for
methods declared by this object. By default, this slot works by appending.
<P></DL>
<H3><A NAME="M31">SLOTTED DEFINITIONS</A></H3>
Some of the configurable definitions of a class or object are <I>slotted
definitions</I>. This means that the configuration is implemented by a slot
object, that is an instance of the class <B>oo::Slot</B>, which manages a list
of values (class names, variable names, etc.) that comprises the contents of
the slot. The class defines three operations (as methods) that may be done on
the slot:
<P>
<DL class="slotted definitions">
<DT><A NAME="M32"><I>slot</I> <B>-append</B> ?<I>member ...</I>?</A><DD>
This appends the given <I>member</I> elements to the slot definition.
<P><DT><A NAME="M33"><I>slot</I> <B>-clear</B></A><DD>
This sets the slot definition to the empty list.
<P><DT><A NAME="M34"><I>slot</I> <B>-set</B> ?<I>member ...</I>?</A><DD>
This replaces the slot definition with the given <I>member</I> elements.
<P></DL>
<P>
A consequence of this is that any use of a slot's default operation where the
first member argument begins with a hyphen will be an error. One of the above
operations should be used explicitly in those circumstances.
<H4><A NAME="M35">SLOT IMPLEMENTATION</A></H4>
Internally, slot objects also define a method <B>--default-operation</B>
which is forwarded to the default operation of the slot (thus, for the class
&#8220;<B>variable</B>&#8221;
slot, this is forwarded to
&#8220;<B>my -append</B>&#8221;),
and these methods which provide the implementation interface:
<P>
<DL class="slot implementation">
<DT><A NAME="M36"><I>slot</I> <B>Get</B></A><DD>
Returns a list that is the current contents of the slot. This method must
always be called from a stack frame created by a call to <B>oo::define</B> or
<B>oo::objdefine</B>.
<P><DT><A NAME="M37"><I>slot</I> <B>Set </B><I>elementList</I></A><DD>
Sets the contents of the slot to the list <I>elementList</I> and returns the
empty string. This method must always be called from a stack frame created by
a call to <B>oo::define</B> or <B>oo::objdefine</B>.
<P></DL>
<P>
The implementation of these methods is slot-dependent (and responsible for
accessing the correct part of the class or object definition). Slots also have
an unknown method handler to tie all these pieces together, and they hide
their <B>destroy</B> method so that it is not invoked inadvertently. It is
<I>recommended</I> that any user changes to the slot mechanism be restricted to
defining new operations whose names start with a hyphen.
<H3><A NAME="M38">EXAMPLES</A></H3>
This example demonstrates how to use both forms of the <B>oo::define</B> and
<B>oo::objdefine</B> commands (they work in the same way), as well as
illustrating four of the subcommands of them.
<P>
<PRE>oo::class create c
c create o
<B>oo::define</B> c <B>method</B> foo {} {
    puts &quot;world&quot;
}
<B>oo::objdefine</B> o {
    <B>method</B> bar {} {
        my Foo &quot;hello &quot;
        my foo
    }
    <B>forward</B> Foo ::puts -nonewline
    <B>unexport</B> foo
}
o bar                <I><font size="+1">&#8594;</font> prints &quot;hello world&quot;</I>
o foo                <I><font size="+1">&#8594;</font> error &quot;unknown method foo&quot;</I>
o Foo Bar            <I><font size="+1">&#8594;</font> error &quot;unknown method Foo&quot;</I>
<B>oo::objdefine</B> o <B>renamemethod</B> bar lollipop
o lollipop           <I><font size="+1">&#8594;</font> prints &quot;hello world&quot;</I></PRE>
<P>
This example shows how additional classes can be mixed into an object. It also
shows how <B>mixin</B> is a slot that supports appending:
<P>
<PRE>oo::object create inst
inst m1              <I><font size="+1">&#8594;</font> error &quot;unknown method m1&quot;</I>
inst m2              <I><font size="+1">&#8594;</font> error &quot;unknown method m2&quot;</I>

oo::class create A {
    <B>method</B> m1 {} {
        puts &quot;red brick&quot;
    }
}
<B>oo::objdefine</B> inst {
    <B>mixin</B> A
}
inst m1              <I><font size="+1">&#8594;</font> prints &quot;red brick&quot;</I>
inst m2              <I><font size="+1">&#8594;</font> error &quot;unknown method m2&quot;</I>

oo::class create B {
    <B>method</B> m2 {} {
        puts &quot;blue brick&quot;
    }
}
<B>oo::objdefine</B> inst {
    <B>mixin -append</B> B
}
inst m1              <I><font size="+1">&#8594;</font> prints &quot;red brick&quot;</I>
inst m2              <I><font size="+1">&#8594;</font> prints &quot;blue brick&quot;</I></PRE>
<H3><A NAME="M39">SEE ALSO</A></H3>
<B><A HREF="?name=Doc:+next">next</A></B>, <B><A HREF="?name=Doc:+oo::class">oo::class</A></B>, <B><A HREF="?name=Doc:+oo::object">oo::object</A></B>
<H3><A NAME="M40">KEYWORDS</A></H3>
class, definition, method, object, slot
Z a443b97c325cd698a1263aaccd749e68