<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://tcl.activestate.com/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Mon Nov 23 15:46:24 GMT 2009 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='257'>
<header><title>Object Orientation for Tcl</title><author address="mailto:donal.k.fellows@manchester.ac.uk">Donal K. Fellows</author><author address="mailto:will@wjduquette.com">Will Duquette</author><author address="mailto:steve@digitalsmarties.com">Steve Landers</author><author address="mailto:jeffh@activestate.com">Jeff Hobbs</author><author address="mailto:kennykb@acm.org">Kevin Kenny</author><author address="mailto:mig@utdt.edu">Miguel Sofer</author><author address="mailto:richard.suchenwirth-bauersachs@siemens.com">Richard Suchenwirth</author><author address="mailto:lvirden@yahoo.com">Larry W. Virden</author><status type='project' state='final' tclversion="8.6" vote='after'>$Revision: 1.31 $</status><history></history><created day='26' month='sep' year='2005' /><obsoletes tip='50'/></header>
<abstract>This TIP proposes adding OO support to the Tcl core, semantically inspired by XOTcl. The commands it defines will be in the <emph style="bold">::oo</emph> namespace, which is not used by any current mainstream OO system, and it will be designed specifically to allow other object systems to be built on top.</abstract>
<body><section title="Rationale and Basic Requirements">
<para>Tcl has a long history of being comparatively agnostic about object-oriented programming, not favouring one OO system over another while promoting a wealth of OO extensions such as [incr Tcl][<url ref="http://incrtcl.sourceforge.net/itcl/"/>], OTcl[<url ref="http://bmrc.berkeley.edu/research/cmt/cmtdoc/otcl/"/>], XOTcl[<url ref="http://media.wu-wien.ac.at/"/>], stooop[<url ref="http://jfontain.free.fr/stooop.html"/>], Snit[<url ref="http://www.wjduquette.com/snit/"/>], etc. because in general, one size fits nobody.</para>
<para>However, many application domains require OO systems and having a common such base system will help prevent application and library authors from reinventing the wheel each time through because they cannot rely on an OO framework being present with each and every Tcl installation. For example, the http package supplied with Tcl has its own internal object model, and a similar mechanism is reinvented multiple times within tcllib. Other parts of tcllib do their own thing (to say nothing of the fact that both stooop and Snit are in tcllib themselves). This does not promote efficient reuse of each others code, and ensures that each of these packages has a <emph style="italic">poor</emph> object system. The request for an OO system is also one of the biggest feature requests for Tcl, and would make it far easier to implement megawidgets. It also leaves Tcl open to the ill-informed criticism that it doesn&apos;t support OO, despite being spoilt for choice in reality through the extensions listed above.</para>
<para>Given all this, the time has come for the core to provide OO support. The aim of the core OO system shall be that it is simple to get started with, flexible so that it can take you a long way, fast (we all know that we&apos;re going to get compared on this front!), and suitable for use as a foundation of many other things, including the re-implementation of various existing OO extensions, including those that are currently compiled and also those that are pure Tcl extensions.</para>
<para>Another requirement is that programmers should not have to alter all of their existing code in order to get started with the new system; rather, they should be able to adopt it progressively, over time, because it supports better ways of working (e.g., faster and more flexible libraries).</para>
</section>
<section title="The Foundational OO System">
<para>This TIP proposes that the foundation of the OO system should ensure that it is simple, fast and flexible. Semantically, the OO system should be using the semantic model pioneered by OTcl and XOTcl, as leveraging their experience on the complex parts (e.g., the model of multiple inheritance, how to invoke superclass implementations of a method) allows us to go straight to a solution that is rich enough for a very large space of applications.</para>
<para>However, some changes relative to XOTcl are necessary. Certain aspects of XOTcl syntax are peculiar from a conventional OO point-of-view, and it is deeply unfortunate that a very large number of methods are predefined in the XOTcl base class. XOTcl&apos;s approach to object creation options is also highly idiosyncratic (though critical to the way XOTcl itself works) and doesn&apos;t really support the typical Tcl idioms. The changes must be made in such a way that something that works like classic XOTcl for virtually all uses can be built on the new framework, but the core object framework must also enable building [incr Tcl]-like or Snit-like object systems on top.</para>
<para>Note that by keeping things in the base classes comparatively simple, it is much easier to build multiple extended OO frameworks on top.</para>
<subsection title="Key Features">

<subsubsection title="Functional Requirements">
<itemize><item.i><para>Class-based object system. This is what most programmers expect from OO, and it is very useful for many tasks.</para></item.i><item.i><para>Allows per-object customization and dynamic redefinition of classes.</para></item.i><item.i><para>Supports advanced OO features, such as:</para><describe><item.d name='meta-classes'><para>These are subclasses of <emph style="bold">class</emph>, which permit more advanced customization of class behaviour.</para></item.d><item.d name='filters'><para>These are constraints (implemented in Tcl code, naturally) on whether a method may be called.</para></item.d><item.d name='mixins'><para>These allow functionality to be brought into an object from other objects if necessary, enabling better separation of concerns.</para></item.d></describe></item.i><item.i><para>A system for implementing methods in custom ways, so that package authors that want significantly different ways of doing a method implementation may do so fairly simply. Note that this will require additional C code to perform; this API will not be exposed directly to the script level (since it makes little sense there).</para></item.i></itemize>
</subsubsection>
<subsubsection title="Non-Functional Requirements">
<para>Note that these requirements would need to be imposed on any implementation of an object system in the Tcl core code anyway.</para>
<itemize><item.i><para>The speed of the object system is something on which it is easy to predict that Tcl will end up being compared to other languages. Hence, the core OO system <emph style="italic">must</emph> permit efficient implementation.</para></item.i><item.i><para>The core OO system must be clear code that it is easy for the Tcl maintainers to keep in good order. The Engineering Manual <tipref type="text" tip="247"/> will be followed.</para></item.i></itemize>
</subsubsection>
</subsection>
<subsection title="Key Alterations Relative to XOTcl">
<para>The core OO system can be considered to be a derivative of XOTcl, much as C can be considered to be a derivative of Algol. However, like the C/Algol relationship, there are many changes between the core OO system and XOTcl; the <emph style="italic">implementations</emph> are not common.</para>
<itemize><item.i><para>Object and class names in the core extension to be all lower-case, in line with best common practice in general Tcl code.</para></item.i><item.i><para>Methods have to be capable of being non-exported, by which we mean that they are not (simply) callable from contexts outside the object.</para></item.i><item.i><para>The majority of the API for updating an object or class&apos;s definition is to be moved to a separate utility command, <emph style="bold">oo::define</emph>.</para></item.i><item.i><para>More &quot;conventional&quot; naming of operations is to be used.</para></item.i><item.i><para>Many of the more advanced features of XOTcl are not present, especially when it is possible to implement them on top of other features. This particularly applies to:</para><itemize><item.i><para>Filter- and mixin-guards</para></item.i><item.i><para>Invariants</para></item.i><item.i><para>Pre- and post-conditions</para></item.i></itemize></item.i></itemize>
<para>Note that this TIP does <emph style="italic">not</emph> propose to actually include any XOTcl (or Itcl or Snit or ...) compatibility packages in the core; it is about forming a foundation on which they can be built (which happens to also be a comparatively lightweight OO system in itself). Such compatibility packages can either remain separate code, or be the subject of future TIPs.</para>
</subsection>
</section>
<section title="Detailed Rationale for Not Using XOTcl">

<subsection title="Features of XOTcl that are Retained">
<para>Many key semantic features of XOTcl are adopted with little or no change. In particular, the following critical features of the core object system shall be semantically the same as in XOTcl as they represent the best-of-breed in advanced object systems at the moment.</para>
<subsubsection title="Multiple Inheritance">
<para>We shall support multiple inheritance (MI) because this is very difficult to add after the fact.</para>
<para>The main problem with MI in languages like C++ was always confusion caused by the fact that methods were resolved using integer offsets into method tables. By contrast, single inheritance is far too restrictive. By supporting mixins and filters, it becomes possible to build not just conventional OO systems in the C++ or Java mould, but also to make Self-like prototype systems (which requires mixins and subclassing of the class of classes to work) and Aspect-like systems (which require filters for efficient implementation). As these are less well-known terms than those of normal inheritance, we define them here:</para>
<describe><item.d name='mixin'><para>An auxiliary <emph style="italic">class</emph> whose behaviour is &quot;mixed into&quot; the current object or class, adding the mixin&apos;s methods to the target&apos;s methods. Often used to support cross-cutting functionality or object roles.</para></item.d><item.d name='filter'><para>A nominated <emph style="italic">method</emph> that is permitted to control whether all calls to any other method of a class or object occur. This control is achieved by the nominated filter method being chained on the front of the sequence of methods in the &quot;implementation list&quot; for the actual target method. Often used to support transparent orthogonal functionality, such as access control or result caching.</para></item.d></describe>
</subsubsection>
<subsubsection title="The Method Dispatch Algorithm">
<para>The use of a complex class graph model as described above requires a sophisticated algorithm to linearize any particular call of a method into a sequence of method implementations that should be called. This is the method dispatch algorithm. The algorithm works by scanning the graph of the object and its associated classes in the order given below, collecting implementations as they are found in a list, with an implementation coming in the <emph style="italic">last</emph> position in the list it can be; if it would be in twice because of an &quot;inheritance diamond&quot;, it comes in the later location.</para>
<enumerate><item.e index='1'><para>Filters defined on classes mixed into the object or its class (or superclasses), with filters from a particular class processed in the order that they are described by that class.</para></item.e><item.e index='2'><para>Filters defined on the object, in the order that they are described in the object&apos;s filter list.</para></item.e><item.e index='3'><para>Filters defined on the class of the object (or its superclasses), with filters from a particular class processed in the order that they are described by that class.</para></item.e><item.e index='4'><para>Methods declared by mixins added to the object, with mixins being processed in the order that they are described in the object&apos;s mixin list (the set of methods declared by the mixin are determined by recursively applying this algorithm).</para></item.e><item.e index='5'><para>Methods declared by mixins added to the object&apos;s class or superclasses, with mixins to a particular class being processed in the order that they are described in the class&apos;s mixin list.</para></item.e><item.e index='6'><para>Methods declared by the object itself.</para></item.e><item.e index='7'><para>Methods declared by the object&apos;s class itself.</para></item.e><item.e index='8'><para>Methods declared by the object&apos;s class&apos;s superclasses, with superclasses being processed in the order that they are described in the class&apos;s superclass list.</para></item.e></enumerate>
<para>Given the above ordering, for each method on an object there is an ordered list of implementations. We dispatch the method by executing the first implementation on the list, which can then hand off to subsequent methods in the list in order using the <emph style="bold">next</emph> command (described below).</para>
<para>Another way to view the ordering is that there are several layers to the ordering scheme. Firstly, there is the basic ordering which is: object, class, superclasses to root (with multiple inheritance being processed in the listed order, and classes appearing in the linearized tree as late as possible). Then there is the second-order ordering, which adds mixins to the front of the basic ordering, where the order of the mixins is processed in basic ordering. Finally, there is the third-order ordering which adds filters to the front of the second-order ordering, with filter name sources being processed in second-order ordering and the method chain for a particular filter being processed in second-order ordering order.</para>
<para>Note that a filter being invoked as a filter is different to a filter being invoked as a normal method. If a filter method is invoked directly, then it will actually be invoked twice, once as a filter and once as a conventional method.</para>
</subsubsection>
</subsection>
<subsection title="Essential Changes Relative to XOTcl">
<para>Unfortunately, not all features of XOTcl are suitable for a core object system. In particular, many more syntactic features need to be altered. This section describes these, together with the rationale for each change; the rationales are marked with the word &quot;<emph style="bold">Therefore</emph>&quot;, in bold.</para>
<subsubsection title="Exported vs. Non-exported Methods">
<para>In XOTcl, every class and every object has an associated namespace. The namespace associated with a class <emph style="italic">::myclass</emph> is <emph style="italic">::xotcl::classes::myclass</emph>; the namespace associated with object <emph style="italic">::myobject</emph> is simply <emph style="italic">::myobject</emph>. XOTcl &quot;instprocs&quot; are simply procs defined in a class (or superclass) namespace; XOTcl per-object &quot;procs&quot; are simply procs defined in an object&apos;s namespace. <emph style="italic">Every such proc becomes an object subcommand.</emph></para>
<para>This is part of the reason why XOTcl objects have such cluttered interfaces. Every method which is of use to the object appears in the object&apos;s interface - and there&apos;s no way to prevent this.</para>
<para><emph style="bold">Therefore</emph>, in the new oo system &quot;<emph style="bold">proc</emph>s&quot; and &quot;<emph style="bold">instproc</emph>s&quot; can be exported or non-exported. Exported procs appear as object subcommands; non-exported procs do not, but remain available as subcommands of the <emph style="bold">my</emph> command. In this way, the object itself can still use them, but they need appear in the object&apos;s interface only if desired.</para>
<para>Additionally, the standard introspection system will need to be extended to allow determining of which methods are exported and which are not.</para>
</subsubsection>
<subsubsection title="The oo::define Command">
<para>In XOTcl, the commands to define per-class methods, filters, and so on are subcommands of the class object; the commands to define per-object methods, filters, and so on are subcommands of the individual object. This is a problem, as it confuses the implementation-time interface with the run-time interface. The design is logical, given XOTcl&apos;s extreme dynamism; any implementation-time activity, such as defining a method or adding a filter can indeed be done at run-time. But again, this makes it difficult to define clean run-time interfaces for reusable library code.</para>
<para>The solution described in the previous section, of making some methods private by declaring them non-exported, does not give us a full solution; having the <emph style="bold">instproc</emph> subcommand available only from instance code isn&apos;t all that useful.</para>
<para><emph style="bold">Therefore</emph>, we add two new commands, <emph style="bold">oo::define</emph> and <emph style="bold">oo::objdefine</emph>, which are used to define methods, filters, and so on. They can be called in two ways, with each command having essentially the same fundamental syntax. The first calling model is as follows:</para>
<quote><emph style="bold">oo::define</emph> <emph style="italic">class subcommand args...</emph></quote>
<quote><emph style="bold">oo::objdefine</emph> <emph style="italic">object subcommand args...</emph></quote>
<para>For example, the following XOTcl code defines a class with two methods:</para>
<verbatim><vline encoding='base64'>eG90Y2w6OkNsYXNzIG15Y2xhc3M=</vline><vline encoding='base64'>bXljbGFzcyBpbnN0cHJvYyBkb3RoaXMge2FyZ3N9IHsgIyBib2R5IH0=</vline><vline encoding='base64'>bXljbGFzcyBpbnN0cHJvYyBkb3RoYXQge2FyZ3N9IHsgIyBib2R5IH0=</vline></verbatim>
<para>In the new oo core, the matching code would be this:</para>
<verbatim><vline encoding='base64'>b286OmNsYXNzIGNyZWF0ZSBteWNsYXNz</vline><vline encoding='base64'>b286OmRlZmluZSBteWNsYXNzIG1ldGhvZCBkb3RoaXMge2FyZ3N9IHsgIyBib2R5IH0=</vline><vline encoding='base64'>b286OmRlZmluZSBteWNsYXNzIG1ldGhvZCBkb3RoYXQge2FyZ3N9IHsgIyBib2R5IH0=</vline></verbatim>
<para>The two definition commands will also have a second calling model, in which they get passed a single definition script whose commands are the subcommands supported by the command as described above:</para>
<quote><emph style="bold">oo::define</emph> <emph style="italic">class script</emph></quote>
<quote><emph style="bold">oo::objdefine</emph> <emph style="italic">object script</emph></quote>
<para>Thus, the above code could also be written as follows:</para>
<verbatim><vline encoding='base64'>b286OmNsYXNzIGNyZWF0ZSBteWNsYXNz</vline><vline encoding='base64'>b286OmRlZmluZSBteWNsYXNzIHs=</vline><vline encoding='base64'>ICAgIG1ldGhvZCBkb3RoaXMge2FyZ3N9IHsgIyBib2R5IH0=</vline><vline encoding='base64'>ICAgIG1ldGhvZCBkb3RoYXQge2FyZ3N9IHsgIyBib2R5IH0=</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>Finally, the constructor for the <emph style="bold">oo::class</emph> class is extended so that such a script can be used during class creation:</para>
<verbatim><vline encoding='base64'>b286OmNsYXNzIGNyZWF0ZSBteWNsYXNzIHs=</vline><vline encoding='base64'>ICAgIG1ldGhvZCBkb3RoaXMge2FyZ3N9IHsgIyBib2R5IH0=</vline><vline encoding='base64'>ICAgIG1ldGhvZCBkb3RoYXQge2FyZ3N9IHsgIyBib2R5IH0=</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>This allows a class to be defined cleanly and concisely, while guaranteeing that all class details can still be modified later on using <emph style="bold">oo::define</emph>.</para>
<para>To enable the easy definition of details of the class object at class definition time, a special subcommand, &quot;<emph style="bold">self</emph>&quot;, will be provided that is equivalent to using <emph style="bold">oo::objdefine</emph> on the class.</para>
<para>Note that because of the requirement for a distinction between public and private interfaces, <emph style="bold">oo::define</emph> and <emph style="bold">oo::objdefine</emph> will need two subcommands XOTcl doesn&apos;t currently provide: <emph style="bold">export</emph> and <emph style="bold">unexport</emph>. <emph style="bold">export</emph> takes as arguments a list of method names; all named methods are exported and become visible in the object or class&apos;s interface. <emph style="bold">unexport</emph> does the opposite. Note that by default, all methods that start with a lower-case letter (specifically, names matching the glob pattern &quot;[a-z]*&quot;) will be exported by default and all other methods will be unexported.</para>
</subsubsection>
<subsubsection title="Standard Metaclasses">
<para>XOTcl defines two standard Metaclasses, <emph style="italic">xotcl::Object</emph> and <emph style="italic">xotcl::Class</emph>. <emph style="italic">xotcl::Object</emph> is the root of the class hierarchy; all XOTcl classes implicitly inherit from <emph style="italic">xotcl::Object</emph>. XOTcl classes are themselves objects, and are instances of <emph style="italic">xotcl::Class</emph>. <emph style="italic">xotcl::Class</emph> can itself be subclassed to produce different families of classes with different standard behaviours.</para>
<para>The new core object system will use the same basic mechanism, based on the metaclasses <emph style="bold">oo::object</emph> and <emph style="bold">oo::class</emph>. However, one of the problems with XOTcl is that XOTcl objects have too much standard behavior; the new core object system must provide a simpler foundation, with the XOTcl behavior optionally available.</para>
<para><emph style="bold">Therefore</emph>, we will extract the features of <emph style="italic">xotcl::Object</emph> and <emph style="italic">xotcl::Class</emph> that are critical into our classes and leave all other functionality up to any subclasses or metaclasses that are defined.</para>
<para>Thus <emph style="bold">oo::object</emph> will be the root of the class hierarchy. However, instances of <emph style="bold">oo::object</emph> will have a minimal set of standard methods, so that clean interfaces can be built on top of it, as can be done with Snit types and instances.</para>
<para>Core object system classes will be instances of <emph style="bold">oo::class</emph> or its subclasses. Likewise, <emph style="bold">oo::class</emph> will define only minimal behaviour.</para>
</subsubsection>
<subsubsection title="Inheritance">
<para>A class may wish to make use of the capabilities of <emph style="bold">oo::class</emph> internally without exporting its methods (e.g., for providing a singleton instance).</para>
<para><emph style="bold">Therefore</emph>, the inheritance mechanism should be extended such that the newly defined class can declare whether a parent class&apos;s methods should be exported or not, on a case-by-case basis. </para>
</subsubsection>
<subsubsection title="Object Creation">
<para>XOTcl has a unique creation syntax. The object name can be followed by what look like Tk or Snit options - but aren&apos;t. Instead, any token in the argument list that begins with a hyphen is assumed to be the name of one of the object&apos;s methods; it must be followed by the method&apos;s own arguments. For example, a standard XOTcl class will have a &quot;set&quot; method, which has the same syntax as the standard Tcl &quot;set&quot; command. Thus, the following code:</para>
<verbatim><vline encoding='base64'>ICAgIG15Y2xhc3MgbXlvYmogLXNldCBhIDEgLXNldCBiIDI=</vline></verbatim>
<para>creates an instance of &quot;myclass&quot; called &quot;myobj&quot; whose instance variables &quot;a&quot; and &quot;b&quot; and set to 1 and 2 respectively. This is an intriguing and innovative interface, and it is unlike any other Tcl object system. Additionally, it makes it difficult to implement standard Tk-like options.</para>
<para><emph style="bold">Therefore</emph>, standard core object system classes will not use this mechanism (though it might be available on demand by inheriting from some other standard metaclass). Instead, standard core object system classes will have no creation behavior other than that implemented by their designers in their constructors.</para>
<para>Constructors may have any argument list the user pleases, including default arguments, the &quot;args&quot; argument (as in the <emph style="bold">proc</emph> command), and XOTcl-style non-positional arguments. It is up to the developer to handle the arguments appropriately.</para>
<para>It is expected that one of the key responsibilities of any XOTcl compatability package would be to define an object/class construction system that parses the arguments in the expected way and uses them to invoke methods on the newly created object.</para>
</subsubsection>
<subsubsection title="Constructor Syntax">
<para>In XOTcl, a class&apos;s constructor is implemented using its &quot;init&quot; instproc. This is troubling; constructors are intended to do things just once, and are often written to take advantage of that, whereas an &quot;init&quot; instproc can theoretically be called at any time. For any given class, then, one of two conditions will obtain: either &quot;init&quot; must be written so that it can be called at any time, or the class will have an inherent logic bug.</para>
<para><emph style="bold">Therefore</emph>, the class constructor will not be implemented as a standard instproc. Instead, the <emph style="bold">oo::define</emph> command will have a new subcommand, <emph style="bold">constructor</emph>, which will be used as follows:</para>
<verbatim><vline encoding='base64'>b286OmRlZmluZSBteWNsYXNzIGNvbnN0cnVjdG9yIHt9IHs=</vline><vline encoding='base64'>ICAgICMgYm9keQ==</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>The constructor so defined will act almost exactly like an instproc; it may call superclass constructors using the &quot;super&quot; command, etc. However, it may never be called explicitly, but only via the class&apos;s &quot;create&quot; and &quot;new&quot; methods.</para>
</subsubsection>
<subsubsection title="Destructor Syntax">
<para>In XOTcl, a class&apos;s destructor is defined by overriding the &quot;destroy&quot; instproc. This is problematic for two reasons: first, a destructor doesn&apos;t need an argument list. An instproc is too powerful for the task. Second, successful destruction should not depend on the destructor&apos;s chaining to its superclass destructors properly.</para>
<para><emph style="bold">Therefore</emph>, the class destructor will be defined by a new subcommand of <emph style="bold">oo::define</emph>, <emph style="bold">destructor</emph>, as follows:</para>
<verbatim><vline encoding='base64'>b286OmRlZmluZSBteWNsYXNzIGRlc3RydWN0b3Igew==</vline><vline encoding='base64'>ICAgICMgQm9keQ==</vline><vline encoding='base64'>fQ==</vline></verbatim>
<para>The destructor has no argument list.</para>
<para>The destructor cannot be called explicitly. Instead, the destructors are invoked in the proper order by the standard <emph style="bold">destroy</emph> method (defined in <emph style="bold">oo::object</emph>), which need never be overridden.</para>
<para>If an error occurs in a destructor, it will <emph style="italic">not</emph> prevent the object from being deleted. There is no guarantee to run destructors when an interpreter or Tcl-enabled process exits.</para>
</subsubsection>
<subsubsection title="Behavior and Syntax of next">
<para>In XOTcl, the <emph style="bold">next</emph> command is used to invoke the &quot;next&quot; method in the dispatch chain. It optionally takes arguments to process (if they are omitted, it passes all arguments that were passed to the current method) and it calls the appropriate superclass implementation. But it does so without adjusting the Tcl stack, which forces classes to take extreme care when implementing code that needs to access variables or evaluate scripts in the scope of the code that invoked the method in the first place.</para>
<para><emph style="bold">Therefore</emph>, the <emph style="bold">next</emph> command will perform Tcl stack management so that using <emph style="bold">uplevel</emph> and <emph style="bold">upvar</emph> in a method will be just like doing so in a normal procedure, no matter how the class containing that method is subclassed.</para>
<para>In addition, the adoption of <tipref type="text" tip="157"/> makes explicit handling of arguments practical as code does not need to perform potentially troublesome operations with <emph style="bold">eval</emph>, and so <emph style="bold">next</emph> will always require that all argument be passed explicitly. This also makes it easier to decide to pass no arguments to a superclass implementation.</para>
</subsubsection>
</subsection>
<subsection title="Desirable Changes">
<para>The changes described in this section are not absolutely essential to meeting the goals described earlier. However, they are desirable in that they lead to cleaner, more maintainable code.</para>
<subsubsection title="Class vs. Object Method Naming">
<para>XOTcl has many features which can be applied to a class for use by all class instances, or to a single object. For example, a &quot;filter&quot; can be defined for a single object, while an &quot;instfilter&quot; can be defined for a class and applied to all instances of that class.</para>
<para>This is exactly backward. Most behavior will be defined for classes; additional per-object behavior is the special case, and consequently should have the less convenient name.</para>
<para><emph style="bold">Therefore</emph>, all definition subcommands that begin with &quot;inst&quot; will be defined, in the core OO system without their &quot;inst&quot; prefix; the per-object subcommands will be manipulated via <emph style="bold">oo::objdefine</emph> or through the &quot;self&quot; prefix command (described above), to indicate that it is operating on the object itself and not the members of the class. Thus, a filter is defined on a class for its instances using the &quot;filter&quot; subcommand; a filter is defined on a particular object using the &quot;self filter&quot; subcommand (actually a subcommand of a subcommand).</para>
<verbatim><vline encoding='base64'>IG9vOjpkZWZpbmUgc29tZUNscyB7</vline><vline encoding='base64'>ICAgICBtZXRob2QgZm9vIHt9IHsuLi59</vline><vline encoding='base64'>ICAgICBzZWxmIHs=</vline><vline encoding='base64'>ICAgICAgICAgbWV0aG9kIGJhciB7YXJnc30gey4uLn0=</vline><vline encoding='base64'>ICAgICAgICAgZmlsdGVyIGJhcg==</vline><vline encoding='base64'>ICAgICB9</vline><vline encoding='base64'>IH0=</vline></verbatim>
</subsubsection>
<subsubsection title="Procs vs. Methods">
<para>The word &quot;proc&quot; conveys a standalone function; an object&apos;s subcommands are more typically described as its &quot;methods&quot;.</para>
<para><emph style="bold">Therefore</emph>, the core OO system will use &quot;method&quot; in place of &quot;proc&quot; for definitions.</para>
</subsubsection>
<subsubsection title="Public Names">
<para>In XOTcl, the main objects are <emph style="italic">xotcl::Class</emph> and <emph style="italic">xotcl::Object</emph>. However, the Tcl Style Guide dictates that public command names begin with a lower-case letter.</para>
<para><emph style="bold">Therefore</emph>, all public names in the <emph style="italic">oo::</emph> namespace (i.e. the standard classes) will begin with a lower case letter, e.g., the standard core object system equivalents of <emph style="italic">xotcl::Class</emph> and <emph style="italic">xotcl::Object</emph> will be <emph style="bold">oo::class</emph> and <emph style="bold">oo::object</emph>.</para>
<para>This does not constrain any code making use of the OO system from naming objects however it wants.</para>
</subsubsection>
</subsection>
</section>
<section title="API Specification">
<para>This section documents the core object system API in detail, based on the essential and desirable changes discussed in the previous sections.</para>
<subsection title="Helper Commands">
<para>The namespace(s) that define the following three commands are not defined in this specification unless otherwise stated; all that is defined is that they will be on the object&apos;s <emph style="bold">namespace path</emph> during the execution of any method and should always be used without qualification.</para>
<subsubsection title="my">
<para>The <emph style="bold">my</emph> command allows methods of the current object to be called during the execution of a method, just as if they were invoked using the object&apos;s command. Unlike the object&apos;s command, the <emph style="bold">my</emph> command may also invoke non-exported methods.</para>
<quote><emph style="bold">my</emph> <emph style="italic">methodName</emph> ?<emph style="italic">arg</emph> <emph style="italic">arg</emph> ...?</quote>
<para>Note that each object has its own <emph style="bold">my</emph> command; they are all distinct from each other. This means that it is suitable for use for things like invoking callbacks (from general Tcl code) that are non-public methods. In particular, the use of <emph style="bold">namespace code</emph> for encapsulating the use of <emph style="bold">my</emph> for invoking unexported callback methods by non-object code is supported.</para>
<para>Note that the <emph style="bold">my</emph> command does not represent the name of the object.</para>
</subsubsection>
<subsubsection title="next">
<para>The <emph style="bold">next</emph> command allows methods to invoke the implementation of the method with the same name in their superclass (as determined by the normal inheritance rules; if a per-object method overrides a method defined by the object&apos;s class, then the <emph style="bold">next</emph> command inside the object&apos;s method implementation will invoke the class&apos;s implementation of the method). The arguments to the <emph style="bold">next</emph> command are the arguments to be passed to the superclass method. The current stack level is temporarily bypassed for the duration of the processing of the <emph style="bold">next</emph> command; this allows a method to always execute identically with respect to the main calling context without needing to use some form of introspection to determine where that context is on the call frame stack (with a side effect of isolating method implementations from each other).</para>
<quote><emph style="bold">next</emph> ?<emph style="italic">arg</emph> <emph style="italic">arg</emph> ...?</quote>
<para>It is an error to invoke the <emph style="bold">next</emph> command when there is no superclass definition of the current method.</para>
</subsubsection>
<subsubsection title="self">
<para>The <emph style="bold">self</emph> command allows executing methods to discover information about the object which they are currently executing in; it&apos;s always an error if not inside a method. Without arguments, the <emph style="bold">self</emph> command returns the current fully-qualified name of the object (to promote backward compatability). Otherwise, it is a command in the form of an ensemble (though it is not defined whether it is manipulable with <emph style="bold">namespace ensemble</emph>).</para>
<para>The following subcommands of <emph style="bold">self</emph> are defined. None of these subcommands take additional arguments.</para>
<describe><item.d name='caller'><para>Returns a three-item list describing the class, object and method that invoked the current method, respectively. The syntax is as follows:</para><para><emph style="bold">self caller</emph></para></item.d><item.d name='class'><para>Returns the name of the class that defines the currently executing method. If the method was declared in the object instead of in the class, this returns the class of the object containing the method definition. The syntax is as follows:</para><para><emph style="bold">self class</emph></para></item.d><item.d name='filter'><para>When invoked inside a filter, returns a three-item list describing the object or class for which the filter has been registered. The first element is the name of the class or object, the second element is either <emph style="bold">class</emph> (for a filter defined on a class for its instances) or <emph style="bold">object</emph> (for a filter defined on a single object), and the third element is the name of the method. The syntax is as follows:</para><para><emph style="bold">self filter</emph></para></item.d><item.d name='method'><para>Returns the name of the currently executing method. The syntax is as follows:</para><para><emph style="bold">self method</emph></para></item.d><item.d name='namespace'><para>Returns the namespace associated with the current object. The syntax is as follows:</para><para><emph style="bold">self namespace</emph></para></item.d><item.d name='next'><para>Returns a two-element list describing the method that will be executed when the <emph style="bold">next</emph> command is invoked, or an empty list if there is no subsequent definition for the method. The first element of the list is the name of the object or class that contains the method, and the second element of the list is the name of the method. The syntax is as follows:</para><para><emph style="bold">self next</emph></para></item.d><item.d name='object'><para>Returns the name of the current object, the same as if the <emph style="bold">self</emph> command is invoked with no arguments. The syntax is as follows:</para><para><emph style="bold">self object</emph></para></item.d><item.d name='target'><para>When invoked from a filter, returns a two-item list consisting of the name of the class that holds the target method and the name of the target method. The syntax is as follows:</para><para><emph style="bold">self target</emph></para></item.d></describe>
<para>For all these commands, when the name of a method is returned, it will be &quot;<emph style="italic">&lt;constructor&gt;</emph>&quot; when the method is a constructor, and &quot;<emph style="italic">&lt;destructor&gt;</emph>&quot; when the method is a destructor. It should be noted that these are not the actual names of the constructor and destructor (they are unnamed methods); they are just notational conventions supported by the <emph style="bold">self</emph> command.</para>
</subsubsection>
</subsection>
<subsection title="The oo::define Command">
<quote><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="italic">subcommand</emph> ?<emph style="italic">arg</emph> ...?</quote>
<quote><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="italic">script</emph></quote>
<quote><emph style="bold">oo::objdefine</emph> <emph style="italic">object</emph> <emph style="italic">subcommand</emph> ?<emph style="italic">arg</emph> ...?</quote>
<quote><emph style="bold">oo::objdefine</emph> <emph style="italic">object</emph> <emph style="italic">script</emph></quote>
<para>The <emph style="bold">oo::define</emph> command is used to add behavior to classes, and the <emph style="bold">oo::objdefine</emph> command is used to add behavior to objects. The first form of each command is conventional for ensemble-like commands, except that the <emph style="italic">class</emph> or <emph style="italic">object</emph> argument precedes the <emph style="italic">subcommand</emph> argument. In the second form of each command, <emph style="italic">script</emph> is a Tcl script whose commands are the subcommands of <emph style="bold">oo::define</emph> or <emph style="bold">oo::objdefine</emph>; this is a notational convenience, as the two forms are semantically equivalent in what their capabilities are. (Note that the context in which <emph style="italic">script</emph> executes is otherwise not defined.)</para>
<subsubsection title="Class-related Subcommands">
<para>The subcommands of <emph style="bold">oo::define</emph> (which may be unambiguously abbreviated in both the subcommand form and the script form) shall be:</para>
<itemize><item.i><para><emph style="bold">constructor</emph> - this takes two arguments (a <emph style="bold">proc</emph>-style argument list, and a body script), and sets the constructor for the instances of the class to be executed as defined by the body script after binding the actual arguments to the call that creates an instance of the class to the formal arguments listed. The constructor is called after the object is created but before any instance variables are guaranteed to be set. If no constructor is specified, the constructor will accept exactly the same arguments as the constructor in the parent class, and will delegate all the arguments to that parent-class constructor. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">constructor</emph> <emph style="italic">argList</emph> <emph style="italic">body</emph></para><para>Note that constructors of class mixins are also called, but constructors of object mixins are never called (as the object must exist before it can have an auxiliary class mixed into it).</para></item.i><item.i><para><emph style="bold">destructor</emph> - this defines the class destructor; a destructor is like a method but takes no arguments. Destructors are called on all classes that define them when the object is deleted, including classes that have been mixed in. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">destructor</emph> <emph style="italic">body</emph></para><para>Note that destructors <emph style="italic">should always</emph> use the <emph style="bold">next</emph> command within their implementation so that destructors of parent classes are also executed.</para><para>Note also that destructors are called whenever the object is deleted by any mechanism (except when the overall interpreter is deleted, when execution of Tcl scripts has ceased to be possible anyway).</para></item.i><item.i><para><emph style="bold">export</emph> - this specifies that the named methods are exported, i.e., part of the public API of the class&apos;s instances. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">export</emph> <emph style="italic">name</emph> ?<emph style="italic">name</emph> ...?</para><para>An exported method is accessible to clients of the class&apos;s instances; an unexported method is accessible only to the instances&apos; own code through the <emph style="bold">my</emph> command.</para></item.i><item.i><para><emph style="bold">filter</emph> - this subcommand controls the list of filter methods for a class. Each filter method in the list is called when any method is invoked on the class&apos;s instances, and it is up to the filter to decide whether to invoke the filtered method call (using the <emph style="bold">next</emph> command) or return a suitable replacement value. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">filter</emph> ?<emph style="italic">filterName filterName</emph> ...?</para></item.i><item.i><para><emph style="bold">forward</emph> - this subcommand defines a class method which is automatically forwarded (i.e. delegated) to some other command, according to a simple pattern. Each <emph style="italic">arg</emph> is used literally. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">forward</emph> <emph style="italic">name</emph> <emph style="italic">targetCmd</emph> ?<emph style="italic">arg</emph> ...?</para></item.i><item.i><para><emph style="bold">method</emph> - this subcommand (only valid for classes) defines a class method (i.e. a method supported by every instance of the class). By default, methods are exported if they start with a lower-case letter (i.e., any character in \u0061 to \u007a inclusive) and are not exported otherwise. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">method</emph> <emph style="italic">name</emph> <emph style="italic">args</emph> <emph style="italic">body</emph></para></item.i><item.i><para><emph style="bold">mixin</emph> - This subcommand defines a mixin for a class which is a way of bringing in additional method implementations (which may add to or wrap existing methods) on an <emph style="italic">ad hoc</emph> basis. The list of mixins is traversed when searching for methods before the inheritance hierarchy, and mixed-in methods may chain to any methods they override using the <emph style="bold">next</emph> command. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">mixin</emph> ?<emph style="italic">mixinClass mixinClass</emph> ...?</para></item.i><item.i><para><emph style="bold">self</emph> - This subcommand, which has the same syntax patterns as <emph style="bold">oo::objdefine</emph>, allows the manipulation of the class as an object. See <emph style="bold">oo::objdefine</emph> below for a description of the list of subcommands of <emph style="bold">self</emph>. The syntaxes are as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">self</emph> <emph style="italic">subcommand</emph> ?<emph style="italic">arg</emph> ...?</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">self</emph> <emph style="italic">script</emph></para></item.i><item.i><para><emph style="bold">superclass</emph> - This specifies the superclass (or classes) of a class. Note that objects are always either classes or not classes, and cannot be changed from one to the other by any mechanism. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">superclass</emph> <emph style="italic">classList</emph></para></item.i><item.i><para><emph style="bold">unexport</emph> - This specifies that the named methods are unexported, i.e., private. The syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">unexport</emph> <emph style="italic">name</emph> ?<emph style="italic">name</emph> ...?</para><para>An exported method is accessible to clients of the object; an unexported method is accessible only to the object&apos;s own code, through the <emph style="bold">my</emph> command.</para></item.i></itemize>
<para>The following utility subcommands are also supported:</para>
<itemize><item.i><para><emph style="bold">deletemethod</emph> - This deletes one or more methods from a class; it doesn&apos;t modify any definitions of the method in superclasses, subclassses, instances or mixins. The method names must be specified exactly. Syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">deletemethod</emph> <emph style="italic">name</emph> ?<emph style="italic">name</emph> ...?</para></item.i><item.i><para><emph style="bold">renamemethod</emph> - This renames a method in a class from one thing to another; it doesn&apos;t modify any definitions of the method in superclasses, subclassses, instances or mixins. Syntax is as follows:</para><para><emph style="bold">oo::define</emph> <emph style="italic">class</emph> <emph style="bold">renamemethod</emph> <emph style="italic">fromName</emph> <emph style="italic">toName</emph></para></item.i></itemize>
</subsubsection>
<subsubsection title="Per-Object Subcommands">
<para>The following subcommands are all per-object versions of the class subcommands listed above. When they are applied to a class, they operate on the class instance itself as an object, and not on the instances (current and future) of that class (which is why the distinction is required).</para>
<itemize><item.i><para><emph style="bold">class</emph> - This subcommand gets and sets the class of an object. Changing the class of an object can result in many methods getting added or removed. Objects may not be changed between being class-objects and and non-class objects. The syntax is as follows:</para><para><emph style="bold">oo::objdefine</emph> <emph style="italic">object</emph> <emph style="bold">class</emph> <emph style="italic">className</emph></para><para>Note that when the class is changed of an object, no methods are called on that object, or on either the source or target classes, to indicate that the change has been carried out. This is up to the caller of the <emph style="bold">class</emph> subcommand.</para></item.i><item.i><para><emph style="bold">deletemethod</emph> - This is a per-object version of the <emph style="bold">deletemethod</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i><item.i><para><emph style="bold">export</emph> - This is a per-object version of the <emph style="bold">export</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i><item.i><para><emph style="bold">filter</emph> - This is a per-object version of the <emph style="bold">filter</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i><item.i><para><emph style="bold">forward</emph> - This is a per-object version of the <emph style="bold">forward</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i><item.i><para><emph style="bold">method</emph> - This is a per-object version of the <emph style="bold">method</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i><item.i><para><emph style="bold">mixin</emph> - This is a per-object version of the <emph style="bold">mixin</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i><item.i><para><emph style="bold">renamemethod</emph> - This is a per-object version of the <emph style="bold">renamemethod</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i><item.i><para><emph style="bold">unexport</emph> - This is a per-object version of the <emph style="bold">unexport</emph> subcommand of <emph style="bold">oo::define</emph>, to which it is syntactically identical.</para></item.i></itemize>
</subsubsection>
</subsection>
<subsection title="The oo::copy Command">
<para>The <emph style="bold">oo::copy</emph> command creates an exact copy of an object with the given name. If <emph style="italic">newName</emph> is the empty string or unspecified, a new name will be generated automatically. The syntax is as follows:</para>
<quote><emph style="bold">oo::copy</emph> <emph style="italic">object</emph> ?<emph style="italic">newName</emph>?</quote>
<para>Note that this command does <emph style="italic">not</emph> copy the backing namespace, and nor does it execute any constructors. It is therefore up to the caller to copy such internal state of the object in the manner suitable for the object and its class tree; it is suggested that this be done by wrapping the <emph style="bold">oo::copy</emph> command in another command that defines which method is called.</para>
</subsection>
</section>
<section title="Core Objects">
<para>The following classes are defined, and are the only pre-constructed objects in the core system.</para>
<subsection title="oo::object">
<para>The root of the class hierarchy is <emph style="bold">oo::object</emph>. There are two ways to create a new instance of an object.</para>
<quote><emph style="bold">oo::object</emph> <emph style="bold">create</emph> <emph style="italic">name</emph></quote>
<quote><emph style="bold">set</emph> <emph style="italic">var</emph> <emph style="bold">[</emph> <emph style="bold">oo::object</emph> <emph style="bold">new</emph> <emph style="bold">]</emph></quote>
<para>The first constructs a new object called <emph style="italic">name</emph> of class <emph style="italic">oo::object</emph>; the object is represented as a command in the current scope. The second constructs a new object of class <emph style="bold">oo::object</emph> with a name guaranteed to be different from every existing command and returns the fully qualified of the command created (which it is naturally a good idea to save in a variable, perhaps called <emph style="italic">var</emph>).</para>
<para>The name of an object is also the name of a command in the form of an ensemble where the subcommands of the ensemble are the <emph style="italic">exported</emph> method names of the object. The command is not manipulable with <emph style="bold">namespace ensemble</emph>, but may be renamed.</para>
<para>The new object has one predefined exported method (<emph style="bold">destroy</emph>) and four predefined non-exported methods (<emph style="bold">eval</emph>, <emph style="bold">unknown</emph>, <emph style="bold">variable</emph> and <emph style="bold">varname</emph>). Other subcommands and other behaviour can be added using <emph style="bold">oo::define</emph>.</para>
<para>The <emph style="bold">oo::object</emph> class (an instance of <emph style="bold">oo::class</emph>) serves as the base class for all other core OO system classes.</para>
<subsubsection title="Constructor and Destructor">
<para>The constructor for the <emph style="bold">oo::object</emph> class takes no arguments and does nothing. (The actual construction of an object is special and happens before any constructors are called.)</para>
<para>The destructor does nothing. (The actual destruction of an object is special and happens after all destructors have completed.)</para>
</subsubsection>
<subsubsection title="Methods">
<para>The instances of <emph style="bold">oo::object</emph> (i.e. all objects and classes) have the following methods:</para>
<describe><item.d name='eval'><para>This non-exported method concatenates its arguments according to the rules of <emph style="bold">concat</emph>, and evaluates the resulting script in the namespace associated with the object. The result of the script evaluation is the result of the <emph style="italic">object</emph> <emph style="bold">eval</emph> method. The syntax is as follows:</para><para><emph style="italic">object</emph> <emph style="bold">eval</emph> ?<emph style="italic">arg</emph> <emph style="italic">arg</emph> ...?</para></item.d><item.d name='destroy'><para>This exported method deletes the object; it takes no additional arguments and returns the empty string as its result. The syntax is as follows:</para><para><emph style="italic">object</emph> <emph style="bold">destroy</emph></para></item.d><item.d name='unknown'><para>This non-exported method takes a method name and an arbitrary number of extra arguments and handles the absence of a method with the given name. The default implementation just generates a suitable error message that explains what commands are available given how the caller attempted to invoke the method, and ignores all the additional arguments. The syntax is as follows:</para><para><emph style="italic">object</emph> <emph style="bold">unknown</emph> <emph style="italic">methodName</emph> ?<emph style="italic">arg</emph> ...?</para><para>Note that this method is not normally invoked directly.</para></item.d><item.d name='variable'><para>This non-exported method takes an arbitrary number of <emph style="italic">unqualified</emph> variable names and binds the variable with that name in the object&apos;s namespace to the same name in the current scope, provided the current scope is the body of a procedure, procedure-like method, or lambda term (as used with <emph style="bold">apply</emph>); if executed in a context where the current scope does not admit local variables, this method will have no effect. The syntax is as follows:</para><para><emph style="italic">object</emph> <emph style="bold">variable</emph> ?<emph style="italic">varName</emph> <emph style="italic">varName</emph> ...?</para><para>However, it will be more commonly used as:</para><para><emph style="bold">my variable</emph> ?<emph style="italic">varName</emph> <emph style="italic">varName</emph> ...?</para><para>Each <emph style="italic">varName</emph> argument is the name of a variable in the namespace associated with the object, and must not contain any namespace separators. Each named variable will be bound to a local variable in the current scope with the same name.</para></item.d><item.d name='varname'><para>This non-exported method takes one argument, the name of a variable to be resolved in the context of the object&apos;s namespace, and returns the fully qualified name of the variable such that it can be used with the <emph style="bold">vwait</emph> command or extensions such as Tk (e.g., for the <emph style="bold">label</emph> widget&apos;s <emph style="bold">-textvariable</emph> option). This method does not assign any value to the variable. The syntax is as follows:</para><para><emph style="italic">object</emph> <emph style="bold">varname</emph> <emph style="italic">varName</emph></para><para>However, it will be more commonly used as:</para><para><emph style="bold">my varname</emph> <emph style="italic">varName</emph></para></item.d></describe>
</subsubsection>
<subsubsection title="Unknown Method Handling">
<para>When an attempt is made to invoke an unknown method on any object, the core then attempts to pass <emph style="italic">all</emph> the arguments (including the method name) to the <emph style="bold">unknown</emph> method of the object. The default implementation of the <emph style="bold">unknown</emph> method is specified by the <emph style="bold">oo::object</emph> class, and just generates a suitable &quot;unknown subcommand&quot; error message.</para>
</subsubsection>
</subsection>
<subsection title="oo::class">
<para>This class is the class of all classes (i.e. its instances are objects that manufacture objects according to a standard pattern). Note that <emph style="bold">oo::object</emph> is an instance of <emph style="bold">oo::class</emph>, as is <emph style="bold">oo::class</emph> itself.</para>
<quote><emph style="bold">oo::class</emph> <emph style="bold">create</emph> <emph style="italic">name</emph> ?<emph style="italic">definition</emph>?</quote>
<para>This creates a new class called <emph style="italic">name</emph>; the class is an object in its own right (of class <emph style="bold">oo::class</emph>), and hence is represented as a command in the current scope. <emph style="bold">oo::class</emph> returns the fully qualified command name.</para>
<para>The newly-created class command is used to define objects which belong to the class, just as <emph style="bold">oo::object</emph> is. By default, instances of the new class have no more behaviour than instances of <emph style="bold">oo::object</emph> do; new class behavior can be added to the class in two ways. First, a <emph style="italic">definition</emph> can be specified when creating the class; second, additional behaviour can be added to the class using <emph style="bold">oo::define</emph>.</para>
<para>The definition, if given, consists of a series of statements that map to the subcommands of <emph style="bold">oo::define</emph>. The following three code snippets are equivalent; each defines a class called <emph style="bold">::dog</emph> whose instances will have two subcommands: <emph style="bold">bark</emph> and <emph style="bold">chase</emph>.</para>
<verbatim><vline encoding='base64'>IyBNZXRob2QgMQ==</vline><vline encoding='base64'>b286OmNsYXNzIGNyZWF0ZSBkb2c=</vline><vline encoding='base64'></vline><vline encoding='base64'>b286OmRlZmluZSBkb2cgbWV0aG9kIGJhcmsge30gew==</vline><vline encoding='base64'>ICAgIHB1dHMgIldvb2YsIHdvb2YhIg==</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>b286OmRlZmluZSBkb2cgbWV0aG9kIGNoYXNlIHt0aGluZ30gew==</vline><vline encoding='base64'>ICAgIHB1dHMgIkNoYXNlICR0aGluZyEi</vline><vline encoding='base64'>fQ==</vline></verbatim>
<verbatim><vline encoding='base64'>IyBNZXRob2QgMg==</vline><vline encoding='base64'>b286OmNsYXNzIGNyZWF0ZSBkb2c=</vline><vline encoding='base64'></vline><vline encoding='base64'>b286OmRlZmluZSBkb2cgew==</vline><vline encoding='base64'>ICAgIG1ldGhvZCBiYXJrIHt9IHs=</vline><vline encoding='base64'>ICAgICAgICBwdXRzICJXb29mLCB3b29mISI=</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'></vline><vline encoding='base64'>ICAgIG1ldGhvZCBjaGFzZSB7dGhpbmd9IHs=</vline><vline encoding='base64'>ICAgICAgICBwdXRzICJDaGFzZSAkdGhpbmchIg==</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>fQ==</vline></verbatim>
<verbatim><vline encoding='base64'>IyBNZXRob2QgMw==</vline><vline encoding='base64'>b286OmNsYXNzIGNyZWF0ZSBkb2cgew==</vline><vline encoding='base64'>ICAgIG1ldGhvZCBiYXJrIHt9IHs=</vline><vline encoding='base64'>ICAgICAgICBwdXRzICJXb29mLCB3b29mISI=</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'></vline><vline encoding='base64'>ICAgIG1ldGhvZCBjaGFzZSB7dGhpbmd9IHs=</vline><vline encoding='base64'>ICAgICAgICBwdXRzICJDaGFzZSAkdGhpbmchIg==</vline><vline encoding='base64'>ICAgIH0=</vline><vline encoding='base64'>fQ==</vline></verbatim>
<subsubsection title="Constructor and Destructor">
<para>The constructor for <emph style="bold">oo::class</emph> concatenates its arguments and passes the resulting script to <emph style="bold">oo::define</emph> (along with the fully-qualified name of the created class, of course).</para>
<para>Classes have no destructor by default. (Actual class destruction is special, and happens after all destructors have been executed.)</para>
</subsubsection>
<subsubsection title="Methods">
<para>The instances of <emph style="bold">oo::class</emph> have the following methods:</para>
<describe><item.d name='create'><para>Creates a new instance of the class with the given name. All subsequent arguments are given to the class&apos;s constructor (and so must actually match the syntax pattern specified in the constructor definition). The result of the <emph style="bold">create</emph> method is always the fully-qualified name of the newly-created object. The syntax is as follows:</para><para><emph style="italic">class</emph> <emph style="bold">create</emph> <emph style="italic">objName</emph> ?<emph style="italic">arg</emph> <emph style="italic">arg</emph> ...?</para></item.d><item.d name='new'><para>Creates a new instance of the class with an automatically chosen name. All subsequent arguments are given to the class&apos;s constructor (and so must actually match the syntax pattern specified in the constructor definition). The result of the <emph style="bold">new</emph> method is always the fully-qualified name of the newly-created object. The syntax is as follows:</para><para><emph style="italic">class</emph> <emph style="bold">new</emph> ?<emph style="italic">arg</emph> <emph style="italic">arg</emph> ...?</para><para>Note that the <emph style="italic">oo::class</emph> object itself does not export the <emph style="bold">new</emph> method; it is good practice for all classes to have names.</para></item.d><item.d name='createWithNamespace'><para>Creates a new instance of a class with a given name and a given name of backing namespace. This method (required to provide proper support for putting [incr Tcl] on top of the core OO system) is not exported by default. Apart from the <emph style="italic">nsName</emph> parameter, it is the same as the <emph style="bold">create</emph> method.</para><para><emph style="italic">class</emph> <emph style="bold">createWithNamespace</emph> <emph style="italic">objName nsName</emph> ?<emph style="italic">arg arg</emph> ...?</para></item.d></describe>
</subsubsection>
</subsection>
</section>
<section title="Introspection Support">
<para>The core Tcl <emph style="bold">info</emph> command shall be extended in the following ways.</para>
<subsection title="An [info object] Subcommand">
<para>An <emph style="bold">object</emph> subcommand that shall provide information about a particular object. Its first argument shall be the name of an object to get information about, its second argument shall be a subsubcommand indicating the type of information to retrieve and all subsequent arguments shall be arguments, as appropriate. The following types of information shall be available:</para>
<describe><item.d name='class'><para>Returns the class of an object, or if <emph style="italic">className</emph> is specified, whether the object is (directly or indirectly through inheritance or mixin) an instance of the named class.</para><para><emph style="bold">info object class</emph> <emph style="italic">object</emph> ?<emph style="italic">className</emph>?</para></item.d><item.d name='definition'><para>Returns the formal argument list and body used to define a method.</para><para><emph style="bold">info object definition</emph> <emph style="italic">object method</emph></para></item.d><item.d name='filters'><para>Returns the list of filters defined for an object.</para><para><emph style="bold">info object filters</emph> <emph style="italic">object</emph></para></item.d><item.d name='forward'><para>Returns the list of words that form the command prefix that a method is forwarded to.</para><para><emph style="bold">info object forward</emph> <emph style="italic">object method</emph></para></item.d><item.d name='isa'><para>Returns boolean information about how an object relates to the class hierarchy. Supports a range of subcommands to allow the specification of what sort of test is to be performed:</para><describe><item.d name='class'><para>Returns whether the named object is a class.</para><para><emph style="bold">info object isa class</emph> <emph style="italic">object</emph></para></item.d><item.d name='metaclass'><para>Returns whether the named object is a class that can create other classes (i.e. is <emph style="bold">oo::class</emph> or one of its subclasses).</para><para><emph style="bold">info object isa metaclass</emph> <emph style="italic">object</emph></para></item.d><item.d name='mixin'><para>Returns whether the named object has <emph style="italic">mixinClassName</emph> as one of its mixins.</para><para><emph style="bold">info object isa mixin</emph> <emph style="italic">object mixinClassName</emph></para></item.d><item.d name='object'><para>Returns whether <emph style="italic">object</emph> really names an object.</para><para><emph style="bold">info object isa object</emph> <emph style="italic">object</emph></para></item.d><item.d name='typeof'><para>Returns whether the object is of type <emph style="italic">class</emph> (i.e. an instance of that class or an instance of a subclass of that class).</para><para><emph style="bold">info object isa typeof</emph> <emph style="italic">object class</emph></para></item.d></describe></item.d><item.d name='methods'><para>Returns the list of methods defined for an object. Supports the options <emph style="bold">-all</emph> to also look at the class hierarchy for the object, and <emph style="bold">-private</emph> to get the list of methods supported by <emph style="bold">my</emph> for the object.</para><para><emph style="bold">info object methods</emph> <emph style="italic">object options</emph></para></item.d><item.d name='mixins'><para>Returns the list of mixins for an object.</para><para><emph style="bold">info object mixins</emph> <emph style="italic">object</emph></para></item.d><item.d name='vars'><para>Returns the list of all variables defined within the object, or optionally just those that match <emph style="italic">pattern</emph> according to the rules of <emph style="bold">string match</emph>.</para><para><emph style="bold">info object vars</emph> <emph style="italic">object</emph> ?<emph style="italic">pattern</emph>?</para></item.d></describe>
</subsection>
<subsection title="An [info class] Subcommand">
<para>A <emph style="bold">class</emph> subcommand that shall provide information about a particular class. Its first argument shall be the name of a class to get information about, its second argument shall be a subsubcommand indicating the type of information to retrieve and all subsequent arguments shall be arguments, as appropriate. The following types of information shall be available:</para>
<describe><item.d name='constructor'><para>Returns the formal argument list and body used to define the constructor, or an empty list if no constructor is present.</para><para><emph style="bold">info class constructor</emph> <emph style="italic">class</emph></para></item.d><item.d name='definition'><para>Returns the formal argument list and body used to define a method.</para><para><emph style="bold">info class definition</emph> <emph style="italic">class method</emph></para></item.d><item.d name='destructor'><para>Returns the body of the destructor, or an empty string if no destructor is present.</para><para><emph style="bold">info class destructor</emph> <emph style="italic">class</emph></para></item.d><item.d name='filters'><para>Returns the list of filters defined for a class.</para><para><emph style="bold">info class filters</emph> <emph style="italic">class</emph></para></item.d><item.d name='forward'><para>Returns the list of words that form the command prefix that a method is forwarded to.</para><para><emph style="bold">info class forward</emph> <emph style="italic">class method</emph></para></item.d><item.d name='instances'><para>Returns a list of all direct instances of the class (but not instances of any subclasses of the class), or optionally just those that match <emph style="italic">pattern</emph> according to the rules of <emph style="bold">string match</emph>.</para><para><emph style="bold">info class instances</emph> <emph style="italic">class</emph> ?<emph style="italic">pattern</emph>?</para></item.d><item.d name='methods'><para>Returns the list of methods defined by a class. Supports the options <emph style="bold">-all</emph> to also look at the class hierarchy, and <emph style="bold">-private</emph> to get the list of methods supported by <emph style="bold">my</emph> for the object&apos;s instances.</para><para><emph style="bold">info class methods</emph> <emph style="italic">class options</emph></para></item.d><item.d name='subclasses'><para>Returns a list of all subclasses of the class, or optionally just those that match <emph style="italic">pattern</emph> according to the rules of <emph style="bold">string match</emph>.</para><para><emph style="bold">info class subclasses</emph> <emph style="italic">class</emph> ?<emph style="italic">pattern</emph>?</para></item.d><item.d name='superclasses'><para>Returns a list of all superclasses of the named class in the class hierarchy. The list will be ordered in inheritance-precedence order.</para><para><emph style="bold">info class superclasses</emph> <emph style="italic">class</emph></para></item.d></describe>
</subsection>
<subsection title="Extending the Introspection Capabilities">
<para>Other forms of introspection subcommands may be added to <emph style="bold">info object</emph> and <emph style="bold">info class</emph> by creating exported commands in the namespaces <emph style="bold">oo::InfoObject</emph> and <emph style="bold">oo::InfoClass</emph> respectively.</para>
</subsection>
<subsection title="Issues with Objects and Namespaces">
<para>Every object has a distinct namespace associated with it, the name of which is outside the scope of this specification. It is the name of this namespace that is returned by <emph style="bold">self namespace</emph>.</para>
<para>The namespace does have a path set, as if by calling <emph style="bold">namespace path</emph>; this is how the <emph style="bold">next</emph> and <emph style="bold">self</emph> commands are provided, though since they are never usable outside the scope of the body of a method, the namespace which they originate from is out of the scope of this specification.</para>
<para>The <emph style="bold">my</emph> command is the only command in the object&apos;s namespace by default (i.e., this command is truly per-object). It is not exported from the object&apos;s namespace, nor are any other commands exported from or imported into the namespace.</para>
<para>Methods are not commands, and so completely ignore the <emph style="bold">namespace export</emph> command, nor does <emph style="bold">namespace unknown</emph> get involved at any point during the location of a method. (They may run during the processing of a method body; it is a context very similar to a normal procedure body.) Similarly, a method may not be <emph style="bold">namespace import</emph>ed from another namespace.</para>
<para>Each method (including both the constructor and destructor) executed by an object executes in that object&apos;s namespace. Changes made by a method to the namespace (including both command declaration and uses of <emph style="bold">namespace import</emph>) will be seen by all other methods invoked on the same object. Note that methods declared by classes still execute in the instance objects&apos; namespaces.</para>
</subsection>
</section>
<section title="C API">
<para><emph style="italic">Note: This API is probably incomplete. Future TIPs may extend or completely revise it.</emph></para>
<subsection title="Datatypes">
<para>The following public datatypes shall be declared in tcl.h:</para>
<describe><item.d name='Tcl_Object'><para>An opaque handle to an object.</para></item.d><item.d name='Tcl_Class'><para>An opaque handle to a class.</para></item.d><item.d name='Tcl_Method'><para>An opaque handle to a method.</para></item.d><item.d name='Tcl_ObjectContext'><para>An opaque handle to an object method call context.</para></item.d><item.d name='Tcl_MethodType'><para>A structure describing the type of a method implementation. It shall have the following fields:</para><describe><item.d name='version'><para>The version number of the structure, which should always be referred to as TCL_OO_METHOD_VERSION_CURRENT in source code (currently ignored, but allows transparent versioning in the future).</para></item.d><item.d name='name'><para>The name of the method type, for debugging.</para></item.d><item.d name='callProc'><para>A pointer to a function that defines how to call method implementations of this type. Must not be NULL.</para></item.d><item.d name='deleteProc'><para>A pointer to a function that defines how to delete the <emph style="italic">clientData</emph> associated with a particular method implementation instance. If NULL, no deletion of the <emph style="italic">clientData</emph> is required.</para></item.d><item.d name='cloneProc'><para>A pointer to a function that defines how to copy the <emph style="italic">clientData</emph> associated with a particular method implementation instance during the copying of an object or class with <emph style="bold">oo::copy</emph>. If NULL, the method will be cloned by just copying the <emph style="italic">clientData</emph>.</para></item.d></describe></item.d><item.d name='Tcl_ObjectMetadataType'><para>A structure describing the type of some arbitrary non-NULL metadata attached to an object or class. It shall have the following fields:</para><describe><item.d name='version'><para>The version number of the structure, which should always be referred to as TCL_OO_METADATA_VERSION_CURRENT in source code (currently ignored, but allows for transparent versioning in the future).</para></item.d><item.d name='name'><para>The name of the metadata type, for debugging.</para></item.d><item.d name='deleteProc'><para>A pointer to a function that defines how to delete some metadata associated with this type. Must not be NULL.</para></item.d><item.d name='cloneProc'><para>A pointer to a function that defines how to copy some metadata associated with this type during the copying of an object or class with <emph style="bold">oo::copy</emph>. If NULL, the metadata will not be copied. (<emph style="italic">Open issue:</emph> There is a use case for making objects unclonable; consider the case where the metadata consists of one or more OS resource handles. Simply shallow-copying resource handles is a bad idea, but deep-copying them may well be infeasible. Not all objects can handle copy-on-write semantics gracefully.)</para></item.d></describe></item.d><item.d name='Tcl_MethodCallProc'><para>The type of the <emph style="italic">callProc</emph> field of the Tcl_MethodType structure. It is a pointer to a function that is used to implement how a method implementation is called. It takes five arguments and returns a normal Tcl result code. The arguments are:</para><describe><item.d name='clientData'><para>Some method implementation instance specific data. Note that this is specific to the instance of the method implementation, and not (necessarily) the instance of the object.</para></item.d><item.d name='interp'><para>The Tcl interpreter reference.</para></item.d><item.d name='objectContext'><para>The object method call context, through which useful information (such as what object this method was invoked upon) can be obtained.</para></item.d><item.d name='objc'><para>The number of arguments.</para></item.d><item.d name='objv'><para>The actual list of arguments. Since the number of arguments required to indicate the method may vary, the method implementation should look up how many to skip over using the object method call context.</para></item.d></describe></item.d><item.d name='Tcl_MethodDeleteProc'><para>The type of the <emph style="italic">deleteProc</emph> field of the Tcl_MethodType structure. It is a pointer to a function that is used to delete <emph style="italic">clientData</emph> values associated with a method instance. It takes a single argument (the <emph style="italic">clientData</emph> to delete) and has no return value.</para></item.d><item.d name='Tcl_MethodCloneProc'><para>The type of the <emph style="italic">cloneProc</emph> field of the Tcl_MethodType structure. It is a pointer to a function that is used to make copies of <emph style="italic">clientData</emph> values associated with a method instance suitable for use in another method instance. It takes two arguments (the <emph style="italic">clientData</emph> to clone, and a pointer to a variable into which to write the cloned <emph style="italic">clientData</emph>) and returns either TCL_OK or TCL_ERROR, with the method only being cloned if the result is TCL_OK (the method is silently not cloned otherwise).</para></item.d><item.d name='Tcl_ObjectMapMethodNameProc'><para>The type of a callback function used to adjust the mapping of objects and method names to implementations, which is required to support building [incr Tcl] on top of the core OO system. It takes four arguments, being the interpreter, the object that the method is being invoked upon, a point to a variable to contain the class in the hierarchy to start the search for components of the method chain from, and an unshared object holding the method name as supplied and which can be modified if the method to look for is not the literal name passed in.</para><para>This is necessary because [incr Tcl] allows the invoking of superclass implementations of a method using a syntax like &quot;<emph style="italic">superclassName</emph>::<emph style="italic">methodName</emph>&quot; where <emph style="italic">superclassName</emph> may name any superclass of the current class, and <emph style="italic">methodName</emph> may be any method name.</para><para>Note that the exact definition of this type is subject to change at the moment in order to ensure that it can be connected to the method dispatch engine efficiently. The type will be finalized before the release of Tcl 8.6.</para></item.d><item.d name='Tcl_ObjectMetadataDeleteProc'><para>The type of the <emph style="italic">deleteProc</emph> field of the Tcl_ObjectMetadataType structure. It is a pointer to a function that is used to delete <emph style="italic">metadata</emph> values attached to an object or a class. It takes a single argument (the <emph style="italic">metadata</emph> to delete) and has no return value.</para></item.d><item.d name='Tcl_ObjectMetadataCloneProc'><para>The type of the <emph style="italic">cloneProc</emph> field of the Tcl_ObjectMetadataType structure. It is a pointer to a function that is used to create a copy of <emph style="italic">metadata</emph> values attached to an object or a class. It takes three argument, (the interpreter, the <emph style="italic">metadata</emph> to copy, and a pointer to a variable into which to write the copy, or NULL if the copy is not to be performed) and returns a standard Tcl result code.</para></item.d></describe>
</subsection>
<subsection title="Functions">
<para>The following functional operations are defined:</para>
<describe><item.d name='Tcl_NewMethod'><para>This function creates a new method on a class (and hence on all instances of that class). It has the following signature:</para><para>Tcl_Method <emph style="bold">Tcl_NewMethod</emph>(Tcl_Interp *<emph style="italic">interp</emph>, Tcl_Class <emph style="italic">cls</emph>, Tcl_Obj *<emph style="italic">nameObj</emph>, int <emph style="italic">isPublic</emph>, const Tcl_MethodType *<emph style="italic">typePtr</emph>, ClientData <emph style="italic">clientData</emph>)</para><para>If the method is created with a NULL <emph style="italic">nameObj</emph>, it must be installed manually into the class as a constructor or destructor (in the latter case, it is important that the method be able to execute without additional arguments). Note that a NULL <emph style="italic">typePtr</emph> is reserved for internal use.</para></item.d><item.d name='Tcl_ClassSetConstructor'><para>This function installs a method into a class as a constructor for instances of that class. The method must have been created with <emph style="bold">Tcl_NewMethod</emph> with a NULL <emph style="italic">nameObj</emph> argument. It has the following signature:</para><para>void <emph style="bold">Tcl_ClassSetConstructor</emph>(Tcl_Class <emph style="italic">cls</emph>, Tcl_Method <emph style="italic">method</emph>)</para></item.d><item.d name='Tcl_ClassSetDestructor'><para>This function installs a method into a class as a destructor for instances of that class. The method must have been created with <emph style="bold">Tcl_NewMethod</emph> with a NULL <emph style="italic">nameObj</emph> argument. It has the following signature:</para><para>void <emph style="bold">Tcl_ClassSetConstructor</emph>(Tcl_Class <emph style="italic">cls</emph>, Tcl_Method <emph style="italic">method</emph>)</para></item.d><item.d name='Tcl_NewInstanceMethod'><para>This function creates a new method on an object. It has the following signature:</para><para>Tcl_Method <emph style="bold">Tcl_NewInstanceMethod</emph>(Tcl_Interp *<emph style="italic">interp</emph>, Tcl_Object <emph style="italic">object</emph>, Tcl_Obj *<emph style="italic">nameObj</emph>, int <emph style="italic">isPublic</emph>, const Tcl_MethodType *<emph style="italic">typePtr</emph>, ClientData <emph style="italic">clientData</emph>)</para><para>Note that a NULL <emph style="italic">typePtr</emph> is reserved for internal use, and <emph style="italic">nameObj</emph> must not be NULL.</para></item.d><item.d name='Tcl_NewObjectInstance'><para>This function creates a new instance of a class, calling any defined constructors. It has the following signature, returning NULL (and setting a message in the interpreter) if the object creation failed:</para><para>Tcl_Object <emph style="bold">Tcl_NewObjectInstance</emph>(Tcl_Interp *<emph style="italic">interp</emph>, Tcl_Class <emph style="italic">cls</emph>, const char *<emph style="italic">name</emph>, const char *<emph style="italic">nsName</emph>, int <emph style="italic">objc</emph>, Tcl_Obj *const *<emph style="italic">objv</emph>, int <emph style="italic">skip</emph>)</para><para>Both <emph style="italic">name</emph> and <emph style="italic">nsName</emph> may be NULL, in which case the constructor code picks a default that doesn&apos;t clash with any previously existing commands or namespaces.</para></item.d><item.d name='Tcl_CopyObjectInstance'><para>This function creates a copy of an object (including classes) without copying the backing namespace or executing any constructors. It has the following signature, returning NULL (and setting a message in the interpreter) if the object copying failed:</para><para>Tcl_Object <emph style="bold">Tcl_CopyObjectInstance</emph>(Tcl_Interp *<emph style="italic">interp</emph>, Tcl_Object <emph style="italic">sourceObject</emph>, const char *<emph style="italic">targetName</emph>)</para><para>Note that the copying of an object can fail if the copy code for one of the metadata coping functions fails, so those functions can veto copying. Also note that if <emph style="italic">targetName</emph> is NULL, a name will be picked for the object. Currently no control over the naming of the target object&apos;s namespace is provided.</para></item.d><item.d name='Tcl_GetObjectFromObj'><para>This function converts from a Tcl_Obj holding the name of an object to a Tcl_Object handle. It returns NULL (leaving an error message in the interpreter) if the conversion fails.</para><para>Tcl_Object <emph style="bold">Tcl_GetObjectFromObj</emph>(Tcl_Interp *<emph style="italic">interp</emph>, Tcl_Obj *<emph style="italic">objPtr</emph>)</para></item.d><item.d name='Tcl_ObjectContextInvokeNext'><para>This function invokes the next method implementation in a method call chain, and is the internal implementation of the <emph style="bold">next</emph> command. It has the following signature:</para><para>int <emph style="bold">Tcl_ObjectContextInvokeNext</emph>(Tcl_Interp *<emph style="italic">interp</emph>, Tcl_ObjectContext <emph style="italic">context</emph>, int <emph style="italic">objc</emph>, Tcl_Obj *const *<emph style="italic">objv</emph>, int <emph style="italic">skip</emph>)</para></item.d><item.d name='Tcl_ClassGetMetadata'><para>This function retrieves the metadata attached to the class <emph style="italic">cls</emph> that is associated with the type <emph style="italic">typePtr</emph>. It returns NULL if no data of that type is attached.</para><para>ClientData <emph style="bold">Tcl_ClassGetMetadata</emph>(Tcl_Class <emph style="italic">cls</emph>, const Tcl_ObjectMetadataType *<emph style="italic">typePtr</emph>)</para></item.d><item.d name='Tcl_ClassSetMetadata'><para>This function attaches metadata, <emph style="italic">metadata</emph>, of a specific type, <emph style="italic">typePtr</emph>, to the class, <emph style="italic">clazz</emph>, or removes the metadata of that type if <emph style="italic">metadata</emph> is NULL. It is a no-op to remove metadata of a type that is not attached in the first place.</para><para>void <emph style="bold">Tcl_ClassSetMetadata</emph>(Tcl_Class <emph style="italic">clazz</emph>, const Tcl_ObjectMetadataType *<emph style="italic">typePtr</emph>, ClientData <emph style="italic">metadata</emph>)</para></item.d><item.d name='Tcl_ObjectGetMetadata'><para>This function retrieves the metadata attached to the object <emph style="italic">object</emph> that is associated with the type <emph style="italic">typePtr</emph>. It returns NULL if no data of that type is attached.</para><para>ClientData <emph style="bold">Tcl_ObjectGetMetadata</emph>(Tcl_Object <emph style="italic">object</emph>, const Tcl_ObjectMetadataType *<emph style="italic">typePtr</emph>)</para></item.d><item.d name='Tcl_ObjectSetMetadata'><para>This function attaches metadata, <emph style="italic">metadata</emph>, of a specific type, <emph style="italic">typePtr</emph>, to the object, <emph style="italic">object</emph>, or removes the metadata of that type if <emph style="italic">metadata</emph> is NULL. It is a no-op to remove metadata of a type that is not attached in the first place.</para><para>void <emph style="bold">Tcl_ObjectSetMetadata</emph>(Tcl_Object <emph style="italic">object</emph>, const Tcl_ObjectMetadataType *<emph style="italic">typePtr</emph>, ClientData <emph style="italic">metadata</emph>)</para></item.d><item.d name='Tcl_ObjectGetMethodNameMapper'><para>This function retrieves the current method name mapping function for an object, or NULL if none was set. It has the following signature:</para><para>Tcl_ObjectMapMethodNameProc <emph style="bold">Tcl_ObjectGetMethodNameMapper</emph>(Tcl_Object <emph style="italic">object</emph>)</para></item.d><item.d name='Tcl_ObjectSetMethodNameMapper'><para>This functionsets the method name mapping function for an object, or removes it if the function is set to NULL. It has the following signature:</para><para>void <emph style="bold">Tcl_ObjectSetMethodNameMapper</emph>(Tcl_Object <emph style="italic">object</emph>, Tcl_ObjectMapMethodNameProc <emph style="italic">methodNameMapper</emph>)</para></item.d></describe>
<para>The following pure inspective (i.e., non-state changing) operations are defined:</para>
<describe><item.d name='Tcl_GetClassAsObject'><para>This gets the object that represents a class.</para><para>Tcl_Object <emph style="bold">Tcl_GetClassAsObject</emph>(Tcl_Class <emph style="italic">clazz</emph>)</para></item.d><item.d name='Tcl_GetObjectAsClass'><para>This gets the class that an object represents (or NULL if the object does not represent a class).</para><para>Tcl_Class <emph style="bold">Tcl_GetObjectAsClass</emph>(Tcl_Object <emph style="italic">object</emph>)</para></item.d><item.d name='Tcl_GetObjectCommand'><para>This gets the command for an object. It is the name of this command that represents the object at the script level, and as such, it may be renamed.</para><para>Tcl_Command <emph style="bold">Tcl_GetObjectCommand</emph>(Tcl_Object <emph style="italic">object</emph>)</para></item.d><item.d name='Tcl_GetObjectNamespace'><para>This gets the object&apos;s private namespace.</para><para>Tcl_Namespace *<emph style="bold">Tcl_GetObjectNamespace</emph>(Tcl_Object <emph style="italic">object</emph>)</para></item.d><item.d name='Tcl_MethodDeclarerClass'><para>This gets the class that declared a method, or NULL if the method is a per-object method.</para><para>Tcl_Class <emph style="bold">Tcl_MethodDeclarerClass</emph>(Tcl_Method <emph style="italic">method</emph>)</para></item.d><item.d name='Tcl_MethodDeclarerObject'><para>This gets the object that declared a method, or NULL if the method is a class method.</para><para>Tcl_Object <emph style="bold">Tcl_MethodDeclarerObject</emph>(Tcl_Method <emph style="italic">method</emph>)</para></item.d><item.d name='Tcl_MethodIsPublic'><para>This returns whether a method is a public method. This status might be overridden in subclasses or objects.</para><para>int <emph style="bold">Tcl_MethodIsPublic</emph>(Tcl_Method <emph style="italic">method</emph>)</para></item.d><item.d name='Tcl_MethodIsType'><para>This returns whether a method is a specific type of method, and if so, also returns the <emph style="italic">clientData</emph> for the type. No way of inspecting method types for which you do not have a pointer to the type structure is provided.</para><para>int <emph style="bold">Tcl_MethodIsType</emph>(Tcl_Method <emph style="italic">method</emph>, const Tcl_MethodType *<emph style="italic">typePtr</emph>, ClientData *<emph style="italic">clientDataPtr</emph>)</para></item.d><item.d name='Tcl_MethodName'><para>This returns the name of a method.</para><para>Tcl_Obj *<emph style="bold">Tcl_MethodName</emph>(Tcl_Method <emph style="italic">method</emph>)</para></item.d><item.d name='Tcl_ObjectDeleted'><para>This returns whether an object has been deleted (assuming deletion has not yet completed, i.e., that the destructor is currently being processed).</para><para>int <emph style="bold">Tcl_ObjectDeleted</emph>(Tcl_Object <emph style="italic">object</emph>)</para></item.d><item.d name='Tcl_ObjectContextIsFiltering'><para>This returns whether the method call context is working with a filter or not.</para><para>int <emph style="bold">Tcl_ObjectContextIsFiltering</emph>(Tcl_ObjectContext <emph style="italic">context</emph>)</para></item.d><item.d name='Tcl_ObjectContextMethod'><para>This returns the method call context&apos;s current method instance.</para><para>Tcl_Method <emph style="bold">Tcl_ObjectContextMethod</emph>(Tcl_ObjectContext <emph style="italic">context</emph>)</para></item.d><item.d name='Tcl_ObjectContextObject'><para>This returns the method call context&apos;s object (i.e., the object which was invoked).</para><para>Tcl_Object <emph style="bold">Tcl_ObjectContextObject</emph>(Tcl_ObjectContext <emph style="italic">context</emph>)</para></item.d><item.d name='Tcl_ObjectContextSkippedArgs'><para>This returns the number of arguments to be skipped (this varies because the method instance may be invoked through either [obj method ...] or through [next ...]).</para><para>int <emph style="bold">Tcl_ObjectContextSkippedArgs</emph>(Tcl_ObjectContext <emph style="italic">context</emph>)</para></item.d></describe>
</subsection>
</section>
<section title="Not Addressed in this Document">
<para>This TIP does not address the reqirements for management of variables on a class level or for &quot;class methods&quot; (in the Java sense). These will need to be the subject of future TIPs.</para>
</section>
<section title="Copyright">
<para>This document has been placed in the public domain.</para>
<rule/>
<para>The following sections are non-normative.</para>
</section>
<section title="Appendix: Class Hierarchy for Support of Other OO Systems">
<para>When using the OO system as a basis for some other object system, it is useful for all classes and objects to derive from some other object root for compatability with existing practice. To see how to do this, consider this class hierarchy (targetted at XOTcl) outlined below. The XOTcl <emph style="italic">Object</emph> class would derive from the core <emph style="bold">oo::object</emph> class, and the XOTcl <emph style="italic">Class</emph> class would derive from the core <emph style="bold">oo::class</emph> and the XOTcl <emph style="italic">Object</emph> classes. This would give the following diagram (core classes are in lower case with their namespace omitted, XOTcl classes are in upper case, with namespace omitted).</para>
<verbatim><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgKy0tLS0tLS0tKw==</vline><vline encoding='base64'>ICAgICAgICAgICAgLC0tLS0tLS0+fCBvYmplY3QgfA==</vline><vline encoding='base64'>ICAgICAgICAgICAgfCAgICAgICAgKy0tLS0tLS0tKw==</vline><vline encoding='base64'>ICAgICAgICAgICAgfCAgICAgICAgICAgICxeLg==</vline><vline encoding='base64'>ICAgIGNyZWF0ZXMgfCAgICAgICBfX19fX198X19fX19f</vline><vline encoding='base64'>ICAgICAgICAgICAgfCAgICAgIHwgICAgICAgICAgICAgfA==</vline><vline encoding='base64'>ICAgICAgICAgICAgfCAgKy0tLS0tLS0rICAgICstLS0tLS0tLSs=</vline><vline encoding='base64'>ICAgICAgICAgICAgYC0tfCBjbGFzcyB8ICAgIHwgT2JqZWN0IHw8LS4=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgKy0tLS0tLS0rICAgICstLS0tLS0tLSsgIHw=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgLF4uICAgICAgICAgICAsXi4gICAgIHw=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgIHxfX19fX18gX19fX19ffCAgICAgIHwgY3JlYXRlcw==</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgIHw=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICstLS0tLS0tKyAgICAgICAgIHw=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgIHwgQ2xhc3MgfC0tLS0tLS0tLSc=</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgICAgICstLS0tLS0tKw==</vline></verbatim>
<para>Note that <emph style="bold">class</emph> instances create <emph style="bold">object</emph>s (or subclasses thereof), but <emph style="italic">Class</emph> instances create <emph style="italic">Object</emph>s (or subclasses thereof).</para>
</section>
<section title="Appendix: XOTcl Features Omitted from the Core OO System">

<subsection title="Object Methods">
<para> Object::autoname: This is trivially implemented in a small procedure, and core objects can pick names for themselves and are renameable.</para>
<para> Object::check: Preconditions and postconditions are not supported (they add a lot of complexity) and neither are invariants. Hence, there is no need to control whether they are executed.</para>
<para> Object::cleanup: This is not an especially well-defined method (what if the object happens to hold handles to complex resources such as network sockets; it is not generally possible for the state of the remote server to be reset) and can be added in any compatability layer.</para>
<para> Object::configure: This feature has been deliberately omitted from the core object system. This would be value added by any XOTcl extension.</para>
<para> Object::extractConfigureArg: This feature is part of <emph style="bold">configure</emph>.</para>
<para> Object::getExitHandler: This feature is not necessary for this version. If it existed, it would not need to be a part of the base object.</para>
<para> Object::info: The introspection features are moved into the core <emph style="bold">info</emph> command.</para>
<para> Object::invar: Invariants may be implemented using filters.</para>
<para> Object::move: This feature is equivalent to the use of the standard <emph style="bold">rename</emph> operation.</para>
<para> Object::noinit: This feature has been deliberately omitted from the core object system because its use is dependent on the use of other deliberately-omitted features (i.e., <emph style="bold">configure</emph>). This would be value added by any XOTcl extension.</para>
<para> Object::parameter and Object::parametercmd: The core object system provides tools for doing parameters, but does not provide an implementation on the grounds that it is pretty easy to add.</para>
<para> Object::requireNamespace: Objects always have a namespace.</para>
<para> Object::setExitHandler: See the comments for <emph style="bold">getExitHandler</emph> above.</para>
</subsection>
<subsection title="Class Methods">
<para> Class::__unknown: Auto-loading of unknown classes is handled by the standard core <emph style="bold">unknown</emph> mechanism.</para>
<para> Class::abstract: Abstractness is relatively easy to implement on top of the proposed infrastructure and is not critical to getting an implementation.</para>
<para> Class::allinstances: This feature is trivially implemented in a small procedure.</para>
<para> Class::alloc: The core objects have no default behaviour, so the difference with the basic core class behaviour is moot.</para>
<para> Class::create: Core object creation is a much more sealed process, but the lack of <emph style="bold">configure</emph>-like behaviour means that the complexity of this method is not necessary. Instead, constructors are called automatically.</para>
<para> Class::parameterclass: Core object system parameters are not implemented by classes.</para>
<para> Class::volatile: This feature is omitted as it is believed that it is possible to implement automated lifecycle management as a mixin.</para>
</subsection>
<subsection title="Other Commands">
<describe><item.d name='getExitHandler, setExitHandler'><para>Exit handlers are out of scope for the core object system.</para></item.d></describe>
</subsection>
</section>
</body></TIP>
