我正在尝试在Tcl 8.4.18中实现一个简单的面向对象的系统。我看过Itcl,stooops,XOTtcl等等......并且还没有决定是否要使用它们,特别是如果我能用另一种简单的方法做的话。无论如何,让我说我有一个命名空间
namespace eval Object {
namespace export setvar
proc setvar { model name value } {
set ${model}::${name} $value
}
}
然后我“子类化”如果使用另一个命名空间
namespace eval Model {
namespace import ::Object::*
variable foo 0
}
我可以像这样设置变量
Model::setvar Model foo 2
puts $Model::foo
输出“2”。但是,我想简化代码,以便Object命名空间中的例程“setvar”可以确定它是从“Model”命名空间调用的。像这样:
proc setvar { name value } {
set myspace [namespace current]
set ${namespace}::${name} $value
}
然后将其称为
Model::setvar foo 2
但这不起作用,因为[namespace current]返回“:: Object”而不是“:: Model”。根据文档,因为导入只是引用了对象命名空间。
使用例程setvar的原因是尝试实现变量覆盖,以便我可以使用Model中的foo(如果存在),否则从Object获取它。
还有其他方法吗?或者我应该只使用其他工具之一?
由于
答案 0 :(得分:2)
您正在寻找的代码棘手,但可以做(密钥为namespace which
):
proc setvar { name value } {
set cmdnameScript [list namespace which [lindex [info level 0] 0]]
set myspace [namespace qualifiers [uplevel 1 $cmdnameScript]]]
set ${myspace}::${name} $value
}
如果您使用的是8.5(或更高版本),请考虑将最后set
替换为:
namespace upvar $myspace $name var
set var $value
一旦事情开始变得复杂,一起工作会容易得多。如果做不到这一点,请使用upvar
(几乎同样容易使用,而不是快速,便携式回到Tcl 8.0):
upvar 0 ${myspace}::$name var
set var $value