OTcl Objects (Version 0.96, September 95)

Overview

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

Objects in OTcl are instances of classes. They are created through class objects either implicitly, with a widget command syntax, or explicitly, by calling a creation method. After defining a class Bagel with instprocs flavor and size below, a new bagel object called abagel is created and initialized by calling its flavor and size instprocs. The creation process may be customized for any class. See OTcl Classes for details.

% Class Bagel
Bagel
% Bagel instproc flavor {args} {
  $self set flavors $args
}
% Bagel instproc size {s} {    
  $self set bites $s
}
% Bagel abagel -flavor Sesame -size 12
abagel
% abagel info vars
flavors bites
% abagel set flavors
Sesame
% abagel set bites
12

Once created, objects are manipulated through methods placed on them directly, and methods they inherit from their class object and its superclasses. The former methods are called procs, the latter instprocs. As in Tcl, there is no distinction between system provided methods (such as info and set) and user provided methods (such as flavor and size). Procs take precedence over instprocs, and the order of inheritance for instprocs is discussed under the superclass instproc in OTcl Classes.

All methods are called through the object by using a widget-like syntax. The method name is used as the first argument, with the method's arguments as subsequent arguments. The most specific method that is found either on the object or in its inheritance ordering will be invoked. The flavor and size methods are called on bagels as follows.

% abagel flavor Sesame Onion
Sesame Onion
% abagel size 10
10
% abagel set flavors
Sesame Onion
% abagel set bites
10

Generic objects may be created with the Object class. Object is the repository for the behavior common to all objects. It includes methods for defining new methods and instance variables, initializing and destroying objects, querying them, and so forth. The remainder of this reference page describes these methods. Their functionality can be customized for particular classes or objects by using the standard inheritance mechanisms, or changed directly for all objects by rewriting the methods on Object in Tcl or C.

Alloc

The alloc proc is used to allocate a fresh object that is an instance of class Object. It is normally called by the system as part of object 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 Object alloc proc, no additional arguments are processed, and so they are all returned.

To customize object 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.

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

Array

The array instproc returns information about array instance variables. It mirrors the Tcl array command. See the Tcl array command for options. Array is conceptually defined as follows.

Object instproc array {opt ary args} {
  $self instvar $ary
  eval array [list $opt] [list $ary] $args
}

Class

The class instproc changes the class of an object, where the notion of class is expressed using the names of class objects. The class of an object may be changed at any time, with a run-time type checking system enforcing safety as subsequent methods are executed.

% Class Bagel
Bagel
% Bagel instproc what {} { $self info class }
% Class NewBagel
NewBagel
% Bagel abagel
abagel
% abagel info class
Bagel
% abagel what
Bagel
% abagel set foo bar
bar
% abagel info vars
foo
% abagel class NewBagel
% abagel info class
NewBagel
% abagel what
abagel: unable to dispatch method what
% abagel info vars
foo

Changing the class of an object does not change the instance variables and procs it contains, only the instprocs accessible through it. This may be customized with the standard inheritance mechanisms.

Destroy

The destroy instproc tears down the object, removes it from the interpreter, and releases its memory. Unset traces on instance varaibles are triggered in the process. It takes no arguments, and returns the empty string.

User defined teardown code may be added to objects and classes with the standard inheritance mechanisms.

If the object is also a class, then its instances are destroyed, and classes that depend on it as superclasses have it removed from their superclass list.

There is only one user visible destroy method for both objects and classes. The real teardown work is performed below the method level, through deletion callbacks issued by the Tcl interpreter. This ensures that cleanup will be invoked if the command corresponding to the object is deleted from the interpreter in any manner, including calls to Tcl_DeleteCommand and renaming the command to {}.

% Class Bagel
Bagel
% Bagel instproc destroy {} {
  puts "zap!"
  $self next 
}
% Bagel abagel
abagel
% abagel proc destroy {} {
  puts "poof!"
  $self next
}
% abagel destroy
poof!
zap!
% info commands abagel

While cleanup (including user defined teardown) occurs even if the command is renamed to {}, calling the destroy method is the preferable way to dispose of an object, since error codes cannot be returned if Tcl_DeleteCommand is triggered directly.

Info

The info instproc is used to query the object and retrieve information about its current state. It mirrors the Tcl info command, and has the following options.

In conjunction with other methods such as array and set, these options can recover most information about the state of an object. As an example, the following proc reverse engineers Tcl procs. This is its output when run on itself.

Object proc retrieve {p} {
   set txt [list $self proc $p]
   set al [$self info args $p]
   set dft {}
   for {set i 0} {$i < [llength $al]} {incr i} {
     set av [lindex $al $i]
     if {[$self info default $p $av dft]} then {
       set al [lreplace $al $i $i [list $av $dft]]
     }
   }
   lappend txt $al
   lappend txt [$self info body $p]
   return $txt
}

Init

The init instproc is used to initialize a freshly allocated object that is a direct or indirect instance of the class Object. It is normally called by the system (perhaps from more specialized init instprocs) as part of object creation, but may be called by the user.

init interprets its arguments as pairs of option keys and option values. Each option key should be the name of a valid method for the object, preceded by a dash. The method should take one argument. For each option key and option value pair, init calls the method on the object, with the option value as its argument. It returns the empty string.

To customize object creation, write an init instproc for a class, not an alloc proc. If the option key and option value creation syntax is still desired, then call the Object init instproc by using next. This is discussed in the create instproc in OTcl Classes.

% Class Bagel
Bagel
% foreach i {1 2 3 4} {                    
  Bagel instproc $i {v} {puts $v}
}
% Bagel abagel
abagel
% abagel init -1 one -2 two -3 three -4 four!
one
two
three
four!

init is conceptually equivalent to the following.

Object instproc init {args} {                   
  if {[llength $args]%2 != 0} then {            
    error {uneven number of arguments}          
  }                                             
  while {$args != {}} {                         
    set key [lindex $args 0]                    
    if {[string match {-*} $key]} then {        
      set key [string range $key 1 end]         
    }                                           
    set val [lindex $args 1]                    
    if {[catch {$self $key $val} msg]!=0} then {
      set opt [list $self $key $val]            
      error "$msg during $opt"                
    }                                           
    set args [lrange $args 2 end]               
  }                                             
  return {}                                     
}

Instvar

The instvar instproc is used within the body of a method to map instance variables to local variables. It mirrors the Tcl upvar command (and is implemented in terms of it).

Multiple instance variables may be declared at once. The instance variables may be scalars or arrays (but see below), and need not be previously defined. By default the local alias for an instance variable is the same as the name of the instance variable. Renaming in the style of upvar is specified using a two element lists in the declaration. This departs from Tcl upvar syntax, but allows a simple declaration for the majority of cases, with access to the full functionality of upvar when necessary.

% Class Bagel; Bagel abagel
abagel
% abagel set flavor sesame
sesame
% abagel set size {12 bites}
12 bites
% abagel proc taste {} {
  $self instvar flavor
  return $flavor
}
% abagel taste
sesame
% abagel proc query {} {
  $self instvar size {flavor f} 
  return "$f, $size"
}
% abagel query
sesame, 12 bites

Note that the renaming syntax is required to access individual array elements directly. This is because Tcl's upvar does not allow a remote array element to be locally accessed as an array element. Instead, it is often easier to map the whole array for access.

Next

The next instproc is used within the body of a method to call the next-most shadowed method. It is used to combine inherited methods without depending on explicitly knowing their location. For example, it is typically used as part of init instprocs for classes to form an aggregate initialization method. next is analogous to call-next-method in CLOS. See the superclass instproc in OTcl Classes for a discussion of the order of inheritance.

next searches for an instproc method with the same name as the current method. It begins its search after the position in the precedence ordering where the current method was found, if the current method is an instproc, or from the beginning of the precedence ordering of the object's class, if the current method is a proc. The position information between calls to next is recovered from the class variable. If no next method is found, then an empty string is returned without error. Otherwise, the next method is called with the arguments that were passed to next.

Proc

The proc instproc is used to install proc methods on an object, for sole use by that object. Use proc to customize individual objects beyond the functionality provided by via their class, not for inheritance. With particular argument forms, proc can also remove proc methods from an object, or specify an autoload script for demand loading of the proc method.

The arguments and body of a proc method are of the same form as a Tcl procedure, with two exceptions. If both args and body are empty, then an existing proc method with the specified name is removed from the object. If args is {auto}, then the body is interpreted as an autoload script as described below.

Within the body of the proc and instproc methods, three special variables are defined. These variables are for reading only. Instance variables may be accessed as local variables by using the instvar instproc.

% Class Bagel; Bagel abagel
abagel
% abagel info procs
% abagel proc flavor {f} {  
  $self instvar flavor
  set flavor $f
  return "called $self $proc $f"
}
% abagel info procs
flavor
% abagel flavor sesame
called abagel flavor sesame

Proc and instproc methods may also be declared to autoload. This function is usually accessed through the higher level demand loading scheme described in OTcl Autoloading.

If the argument list is {auto}, then the body is taken to be a script for demand loading of the method. When the method is invoked, the script will be executed (and should cause the real method to be loaded) and then the method will be restarted. While the stub is waiting to load the method body, the method is recognized as a proc by the info method, but cannot be queried for its body or arguments.

% set tmp [open "tmp" w] 
file3
% puts $tmp {abagel proc bagel {} { return "bagel" }}
% close $tmp
% Class Bagel; Bagel abagel
abagel
% abagel proc bagel auto {
    puts -nonewline "loading... "
    source tmp
  }
% abagel bagel 
loading... bagel
% abagel bagel  
bagel

Set

The set instproc is used to place instance variables on an object as well as to access them. It mirrors the Tcl set command (and is implemented in terms of it). It returns the value of the instance variable. Instance variables may be scalar or array variables. They are stored in separate slots than methods, and so are distinct from methods with the same name.

% Class Bagel; Bagel abagel
abagel
% abagel info vars
% abagel set avar aval
aval
% abagel set avar
aval
% abagel set foo(bar) baz
baz
% abagel set foo(bar)
baz
% abagel info vars
foo avar

Unknown

The unknown method, if defined for an object, is invoked by the system when no matching method can be found for regular dispatch. By default, it is not defined for Object, but exists as a hook for user defined handlers, such as abbreviations, load monitoring, error reporting, etc. An unknown instproc that implements implicit creation is defined for Class; see its reference page.

Like Tcl's unknown proc, the unknown method receives as its arguments the name of the method that could not be invoked, along with that method's arguments. The result it returns is returned as the overall result of the call.

As an example, the following unknown instproc implements abbreviations and verbose error messsages.

% Object instproc unknown {m args} {
  foreach i [$self info commands] {
    lappend meth($i) {}
  }
  set cl [$self info class]
  foreach i [concat $cl [$cl info heritage]] {   
    foreach j [$i info instcommands] {
     lappend meth($j) {}
    }
  }
  set abbrev [array names meth "$m*"]
  switch -exact [llength $abbrev] {
     0 { error "$self: invalid method \"$m\": [lsort [array names meth]]" }
     1 { eval [list $self] $abbrev $args }
     default { error "$self: ambiguous method \"$m\": [lsort $abbrev]" }
  }
}
% Object obj    
obj
% obj f
obj: invalid method "f": array class destroy info init instvar next proc set unknown unset
% obj i
obj: ambiguous method "i": info init instvar
% obj d

Unset

The unset instproc is used to remove instance variables from an object. It mirrors the Tcl unset command (and is implemented in terms of it).

% Class Bagel; Bagel abagel
abagel
% abagel set foo bar
bar
% abagel info vars
foo
% abagel unset foo
% abagel info vars