Version 8 of A simple comparison of Tcl object extensions

Updated 2004-02-22 16:27:58

In January of 2004, a poster to comp.lang.tcl asked which of the tcl extensions providing object orientation allowed one to define class members which were other objects.

Several people submitted answers - and some of the answers provided demonstrated how the different extensions might do just that.

Here's some of the examples provided:


Snit

 snit::type C2 {
    variable this
    variable that

    constructor {args} {
        set this [C2 %AUTO%]
        set that [C2 %AUTO%]
    }

    destructor {
        catch {$this destroy}
        catch {$that destroy}
    }

    method doThis {} {
        $this doSomething
    }

    method doThat {} {
        $that doSomething
    }
 }

Peter Lewerin: shouldn't it be like this:

 snit::type C1 {
    option -partof
    method doSomething {} {
        puts "[$self cget -partof]'s $self doin' it"
    }
 }

 snit::type C2 {
    delegate method doThis to this as doSomething
    delegate method doThat to that as doSomething

    constructor {args} {
        install this using C1 %AUTO% -partof $self
        install that using C1 %AUTO% -partof $self
        $self configurelist $args
    }

    destructor {
        catch {$this destroy}
        catch {$that destroy}
    }
 }

incr Tcl

  itcl::class C1 {
  }

  itcl::class C2 {
      variable m1
      variable m2
      constructor {} {
          set m1 [C1 #auto]
          set m2 [C1 #auto]
      }
      destructor {
          itcl::delete object $m1 $m2
      }
  }

stooop

 class C2 {
     proc C2 {this} {
         set ($this,o1) [new C1]
         set ($this,o2) [new C1]
     }
     proc ~C2 {this} {
         delete $($this,o1) $($this,o2)
     }
     class C1 {
         proc C1 {this} {}
         proc ~C1 {this} {}
     }
 }
 delete [new C2]

XOTcl

There are some posibilities

Example 1 (generate global objects in the constructor and refer to it via instance variables)

   Class C1
   Class C2
   C2 instproc init {} {
       my instvar o1 o2
       set o1 [C1 new]
       set o2 [C1 new]
   }
   C2 instproc destroy {} {
       my instvar o1 o2
       $o1 destroy
       $o2 destroy 
       next
   }

Example 2 (by using anonymous nested objects. Does not need to destroy explicit the sub-objects)

Sub-objects are better to implement aggregation or membership (part of, has a)

   Class C1
   Class C2 -parameter {o1 o2}
   C2 instproc init {} {
       my o1 [C1 new -childof [self]]
       my o2 [C1 new -childof [self]]
   }

Example 3 (by using named sub-objects. Does not need to destroy explicit the sub-objects)

Quite similar to C++ object members

   Class C1
   Class C2
   C2 instproc init {} {
       C1 create [self]::o1
       C1 create [self]::o2  
   }

Example 4 (by using anonymous sub-objects generated via parameters. Sub-objects are destroyed automatically when container is deleted)

Quite similar to example 2, but no need for a explicit constructor

    ::xotcl::Class::Parameter C1
    Class C2 -parameter {
      {o1 -Class C1 -default 1}
      {o2 -Class C1 -default 1}
    }

Category Object Orientation | Category Example