OTcl Classes (Version 0.96, September 95)

Overview

This reference page describes the functionality provided for all classes by methods on the Class class. See the tutorial for an introduction to programming in OTcl, and the C API page for details of manipulating classes from C.

Classes in OTcl are a special kind of object used mainly for inheritance. By convention, they are named with mixed case to distinguish them from regular objects. They inherit all the abilities of regular objects from Object, and add more. The inherited behavior includes method lookup, dispatch, and combination, and initialization syntax. See Objects in OTcl to understand these abilities of regular objects.

Classes are created through meta-class objects, either implicitly with a widget command syntax, or explicitly by calling a creation method. Generic classes may be created with the Class class. By default, they will inherit from Object. The classes Bagel, and SuperBagel, which inherits from Bagel, may be defined as follows. See the create instproc for a description of the overall creation process and how to customize it.

% Class Bagel
Bagel
% Bagel info class
Class
% Bagel info superclass
Object
% Class SuperBagel -superclass Bagel
SuperBagel
% SuperBagel info class
Class
% SuperBagel info superclass
Bagel

Class is the repository for the behavior common to all classes. It includes methods for defining new methods for use by instances, initializing and destroying classes, specifying their superclasses, querying them, and so forth. The remainder of this reference page describes these methods. Their functionality can be customized for particular meta-classes or classes by using the standard inheritance mechanisms, or changed directly for all classes by rewriting the methods on Class in Tcl or C.

Alloc

The alloc proc is used to allocate a fresh class object that is an instance of class Class and has superclass Object. It is normally called by the system as part of class creation, but may be called by the user.

The system create instproc on Class expects all alloc procs to take the name of the object to allocate, and a list of arguments. It expects them to allocate the object, install it in the interpreter, and return the list of unprocessed arguments. For the case of the Class alloc proc, no additional arguments are processed, and so they are all returned.

To customize class creation, write an init instproc, not an alloc proc. New alloc procs will typically be written in C to allocate structurally different types of object.

% Class alloc foo bar baz
bar baz
% foo info class
Class
% foo info procs
% foo info vars

Create

The create instproc provides a mechanism for classes to create other classes and objects. It is invoked by the default unknown instproc if no matching method name can be found, and so may be ellided to yield the familiar widget-like creation syntax.

create takes the name of a class or object to create plus extra initialization argument pairs, and returns the name of the object or class created. It effectively calls an alloc proc to allocate the object, then dispatches the init method with the initialization arguments to initialize the object. Recall that the base init method on Object interprets these arguments as option key and option value pairs, evaluating each pair in turn. The following three sequences are essentially equivalent (except in terms of return value).

% Class create Bagel
Bagel
% Class Bagel
Bagel
% Class alloc Bagel
% Bagel init

The alloc proc that is called by create is determined by the class object on which it is called. create first looks for an alloc proc on this class object, then on its superclasses according to the precedence ordering. The result is that calling create on Class (or a class specialized from it) will create a new class, whereas calling create on Object (or a class specialized from it) will create a new object.

Classes may customize the initialization of their instances by defining an init instproc. If the option key and option value creation syntax is still desired, this init instproc should combine its behavior with the init instproc on Object by using the next instproc, as shown below. For example, the class Bagel may require an instance variable called bites to be initialized to a default value of 12, in addition to regular option key and option value initialization. This is accomplished as follows. (The use of eval is simply to flatten the list of arguments contained in args.) Similarly, an init instproc on Class may be used to customize the initialization of all classes.

% Class Bagel
Bagel
% Bagel instproc init {args} {
  $self set bites 12
  eval $self next $args
}
% Bagel instproc flavor {f} {
  $self set flavor $f
}
% Bagel abagel -flavor sesame
abagel
% abagel set bites
12
% abagel set flavor
sesame

Alternatively, the standard inheritance mechanisms may be used to provide some or all classes with their own create proc, allowing complete control over the creation process. For reference, the default create instproc on Class is conceptually defined as follows.

Class instproc create {obj args} {              
  set h [$self info heritage]                   
  foreach i [concat $self $h] {                 
    if {[$i info commands alloc] != {}} then {  
      set args [eval [list $i] alloc [list $obj] $args]       
      $obj class $self                          
      eval [list $obj] init $args                      
      return $obj                               
    }                                           
  }                                             
  error {No reachable alloc}                    
}

Info

The info instproc is used to query the class and retrieve information about its current state. It mirrors the Tcl info command, and has the following options in addition to those of the Object info instproc.

These options can recover most information about the state of a class. As an example, the following instproc returns a list of all direct and indirect instances of a class.

Class instproc instances {} {
  set il {}
  foreach i [Class info instances] {
    if {[$self info subclass $i]} then {
      eval lappend il [$i info instances]
    }
  }
  return $il
}

Instproc

The instproc instproc is used to install instproc methods on a class, for use by that class's direct and indirect instances. Use instproc to share and inherit behaviors. With particular argument forms, instproc can also remove instproc methods from a class, or specify an autoload script for demand loading of the instproc method.

The arguments and body of an instproc method are of the same form as a Tcl procedure, with two exceptions. If both args and body are empty, then an existing instproc method with the specified name is removed from the class. If args is {auto}, then the body is interpreted as an autoload script in the same manner as described under the proc instproc in OTcl Objects. See OTcl Autoloading for a higher level demand loading scheme.

The following example demonstrates defining instprocs, using them on behalf of and object, and combining their functionality with next.

% Class Bagel
Bagel
% Class SuperBagel -superclass Bagel
SuperBagel
% Bagel instproc taste {} {
  puts yum!      
}
% SuperBagel instproc taste {} {
  $self next
  puts YUM!
}
% SuperBagel abagel
abagel
% abagel taste
yum!
YUM!

The environment in effect when an instproc is being executed is the same as when a proc is being executed, and is described under the proc instproc in OTcl Objects. The special variable class may be used for a variety of tasks, such as to access shared variables stored on the class object. For example, the default size of a bagel in bites may be stored on the Bagel class to be accessed during the init instproc as follows.

% Class Bagel
Bagel
% Bagel set bites 12
12
% Bagel instproc init {args} {
  $class instvar bites
  $self set size $bites
  eval $self next $args
}
% Bagel abagel
abagel
% abagel set size
12
% Bagel set bites 7
7
% Bagel abagel
abagel
% abagel set size
7

Superclass

The superclass instproc is used to change the superclasses from which a class directly inherits behavior. It takes one argument that is a list of superclasses and returns the empty string. The order of the superclass list determines the order of inheritance. Multiple inheritance is supported.

The superclasses must be in precedence order (from most specialized to least specialized) if they are related, and the resulting superclass relation must be cycle-free. An error is returned and the superclass graph is unchanged if either of these conditions are unmet.

The linear precedence order in which superclasses are searched for instprocs is constrained according to each local superclass list. It is guaranteed that if A inherits from B and C, then A will behave like a B before it behaves like a C, and so forth for B and C and their superclasses. The algorithm used to generate this ordering is an unspecified CLOS-like topological sort of the inheritance graph. (This is all you need to know. Multiple inheritance is best thought of in terms of local orderings. If you are relying on subtleties of the global ordering, then you are asking for trouble.)

The heritage option of the info instproc may be used to discover the precedence order, and hence the path that the next instproc will use when instructed to combine methods.

Unknown

The unknown instproc for classes is used to implement implicit creation of objects. It is invoked when no matching method is found, and interprets the method name as the name of an object to be created with create, thus allowing a widget-like creation syntax.

See the entry for unknown in OTcl Objects for a general description of the unknown method mechanism.

The unknown instproc on Class is conceptually defined as follows. It you do not want implicit creation, then redefine or remove the default method with the instproc method.

Class instproc unknown {m args} {       
  if {$m == {create}} then {            
    error "$self: unable to dispatch $m"
  }                                     
  eval [list $self] create [list $m] $args 
}