I'm starting to write a framework in tcl which uses TclOO.
I intend to keep a central library of core classes. Child classes will live in separate files which need to be able to source the core classes to derive from them. Using tcl source
to obtain the core class definition doesn't feel right and I was wondering whether packages would do a better job.
Before going down this rabbit hole I'd like to know if this could work in principle.
CodePudding user response:
tl;dr: YES
I suggest you put the classes in namespace
s (as many as makes sense but usually within one or as children of one), with the code stored in files that are ostensibly source
able but which are actually part of the implementation of a package
. The main tricky thing is that if you source
a file that creates a class twice, the second time is likely to fail because of the already existing class; that only really matter for development. When you're just using the classes in the package, that won't be a problem.
The name of the main namespace for your code and the name of the package ought to be exactly the same. It's not required because of all the legacy things that don't follow the convention, but it is a good convention to follow in order to avoid tremendous confusion. (Any helper things can go in sub-namespaces of the main namespace; it's common to regard those as implementation details.)
Namespaces are named entities that hold commands, variables and other namespaces. They exist within the context of an executing Tcl interpreter. The only truly special namespace is the global namespace, usually called ::
by convention though its name is actually empty. However a few others are best regarded as special (such as ::tcl
for bits of Tcl's implementation, and :oo
for TclOO).
TclOO objects are a mix of commands and namespaces: specifically two commands and one namespace per object (the namespace is usually a child of ::oo
with a dynamic name). The namespace holds the instance variables of the object and a bunch of other things, and the commands are the public name of the object and its my
command (put in its namespace). Classes are just objects... with some extra metadata hung off the back. (Methods aren't commands; they've got a different C type signature.)
The source
command is extremely stupid: it just reads the file and evaluates it, with virtually no smarts at all. The smarts in that area are in package
, which groups collections of related files together and gives them a common name and version: when you do package require
it ends up doing the appropriate source
commands to read the implementation. Or maybe it does load
(if the package has an implementation in C or something else that generates a suitable DLL) or even a mix of source
and load
. The point is, as a user of a package you shouldn't have to care how it is implemented, just that you've asked for it and been given it.
CodePudding user response:
Developing myself frameworks using TclOO, I find auto loading very useful. On top of these frameworks, I have a helper package, defining an "auto_load_class" command to setup auto loading:
oofmk::auto_load_class srcdir \
className className ...
will fill auto_index($className) to source $srcdir/$className.tcl.
Alternate syntax can also place several classes in same file:
oofmk::auto_load_class srcdir \
{className otherClassName}
expect to find otherClassName in $srcdir/$className.tcl too.
The package redefines slots superclass and mixin to perform class auto loading.