My first experiences with OO extensions in Tcl/Tk was Itcl which I used intensively on programming my CMS One Hand Content. This extension worked mostly as expected – with a few pitfalls and one thing I found annoying: options were mapped to internal variables of the objects. More than once I ran in danger of name collision inside method definitions.
Then, I found Snit and really enjoyed it. Especially, options are mapped to key/value pairs of an array. No more danger of name collision! — Instead of heritage, components are installed where methods and options can be delegated to: really great! — But, I found the hint that performance disappoints if there are many once-used local objects. But that was exactly what I wanted in my current project on computer-generated cartoons.
So, I made obj — just another OO system. It does not seamlessly fit into Tk's object approach, and it is far from being complete. But it is minimalistic, and it is (at least intended to be) quite fast. It is made as follows:
The basic procedures are located in namespace ::obj
. An object class resides in an own namespace below basic procedures — ::obj::class::classname
— where its methods are located as well as the array data
with the individual data for the instances.
A method is just a procedure where the instance name is first argument. The first argument variable is fixed to the name self
. The procedure ::obj::method
automates that.
Besides a few pre-defined prcedures and methods, here resides the basic procedure _root-object_
which is the master procedure for all method calls.
An instance is created as follows:
_root-object_
is referenced with the Tcl expression namespace import
.::obj::inst::1
— which is the object's tag. It can always be referenced by the Tcl command ::info level 0
.::obj::inst::1 method1 ...
, then the referenced procedure _root-object_
calls method1 ::obj::inst::1 ...
inside its namespace.The consequences are:
$o
._root-object_
. I expect that this fact increases the speed in comparison to Snit, if many (possibly anonymously created) instances are used just once.Obj does not provide class heritage as used by Itcl, but instead component delegation as used by Snit, as follows:
Besides options, an instance $o
can have private data with the statement:
$o private key val
If val
is the name of an instance, then it can be treated as component with the statement:
$o component key method1 ...
Differently to other object systems, no mapping to Tcl variables, instead instance-internal values are accessible only by the methods configure
, cget
, private
, and common
, and the abbreviation procedures my
and our
.
Differently to Itcl, methods are realized as procedures, but not mapped to procedures. Inside method definitions, own methods must always invoked via $self method1 ...
. The advantage is: no confusion with regular procedures.
If you wish that every instance of class dog
has a private component tail
, then write the appropriate constructor:
% ::obj::constructor dog {} { $self private tail [new tail] } constructor dog %
If you wish that every method call wag
on an instance of dog
is done by its component tail
, then delegate it as follows:
% ::obj::delegate method wag dog tail class dog delegates method wag to component tail. %
You can do the same with options, e.g. -length
. — For more details, see the documentation.
If you work with inherited objects of other object systems, e. g. Snit, or Itcl, then you can use their instances as components of obj instances. They live peacefully side-by-side. As delegation of methods and options just triggers an appropriate method definition, delegating obj things to Itcl components works as well as to own objects!
© Wolf-Dieter Busch | Home | Sitemap | Urheber | A-Z