Tcl如何从导入的例程中确定导入器的命名空间

时间:2012-03-25 20:42:19

标签: import namespaces tcl

我正在尝试在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获取它。

还有其他方法吗?或者我应该只使用其他工具之一?

由于

1 个答案:

答案 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