Author: Gerald Lester <[email protected]>
Author: Donal K. Fellows <[email protected]>
State: Final
Type: Project
Vote: Done
Created: 18-Oct-2017
Post-History:
Keywords: Tcl
Tcl-Version: 8.7
Votes-For: DKF, AK, JD, SL, JN
Votes-Against: none
Tcl-Branch: tip-478
Abstract
TclOO provides a native OO system for Tcl. This TIP is to enhance it to meet some of the common expectations of people coming in from other languages.
Rationale
Most other OO systems provide for class variables which are accessible and shared by all members of a class and class methods which only have access to class variable and not to instance/object variables. They also provide a way to initialize the class variables. This TIP seeks to add them into TclOO.
Proposal
The proposal is to add some or all of the functionality of oo::util
, in particular the classvariable
and classmethod
.
Additionally, it is proposed to add an initialise
class definition command to all the initialization of class variables.
New Basic Features
The myclass
command (created in each object's namespace) allows any method
(exported or unexported) of the current class of the owning object to be
invoked. It is like using info object class
to look up the class of the
current object, info object namespace
to find the namespace of the class,
then using the my
command in that namespace (assuming that it hasn't been
renamed). This is implemented in C so it is fast, effective, and robust.
New Metaclasses
The oo::singleton
metaclass only allows a single instance of the class that
it is mixed into to exist at a time. It hides the create
method on the class and
implements a cache so that the new
method will only create an instance of
the class if there is not an existing instance. Subclasses of the singleton
class are not restricted.
The oo::abstract
metaclass does not allow any instances of the class that it
is mixed into to be created, hiding the instantiation methods (create
,
new
, etc.) of that class. The class can still be inherited from and those
subclasses can be instantiated.
New Definitions
The classmethod
class definition creates a method that can be used when
invoked against its defining class or any of its subclasses. When a class
method is invoked on the class or any of its subclasses, the current object
(i.e., the object reported by self
) will be the class on which it is invoked
(i.e., the subclass if it is invoked against a subclass). When a class method
is invoked on an object that is an instance of the class or any of its
subclasses, the current object will be the current class of the object on
which the method was invoked. Thus:
oo::class create Super {
classmethod x {} {puts "self is [self]"}
}
oo::class create Sub {superclass Super}
set instSuper [Super new]
set instSub [Sub new]
Super x; # prints 'self is ::Super'
Sub x; # prints 'self is ::Sub'
$instSuper x; # prints 'self is ::Super'
$instSub x; # prints 'self is ::Sub'
The initialise
class definition evaluates a script in a context where it can
access the class's namespace, allowing for easier initialisation of a class
than simply overriding its constructor. It has the alternate name,
initialize
. In particular, this makes it much easier to create procedures
and variables in that namespace.
New Helper Commands
The callback
/mymethod
command, available within methods, takes the name of
a method and zero-or-more arguments and returns a script fragment that will
allow that method easy to invoke from a callback (e.g., a variable trace
,
chan event
callback, or Tk event binding). The command will be available
with both names.
The classvariable
command, available within methods, binds a local variable
to a variable within the namespace of the class that defined the method.
The link
command, available within methods, creates a binding for methods
so that calling the command with the given name is equivalent to calling
my $name
instead. It can link multiple methods with one call, one per
argument, and those created commands can be renamed without losing the link;
if an argument is a two-element list, the first element is the name of the
method and the second is the name of the command (which will be resolved
relative to the current namespace if it is not an absolute command name).
Reference Implementation
Reference implementations are mentioned in the proposal section. Additionally, this is a reference implementation for initialise
:
proc ::oo::define::initialise {body} {
set clsns [info object namespace [uplevel 1 self]]
tailcall apply [list {} $body $clsns]
}
This is a reference implementation for oo::abstract
:
oo::class create oo::abstract {
superclass oo::class
unexport create createWithNamespace new
}
Copyright
This document has been placed in the public domain.