【发布时间】:2023-03-25 07:48:01
【问题描述】:
我正在对来自 Tcl8.6 和 Rivet 的 TclOO 进行一些试验,但我遇到了麻烦,因为我无法做我想做的事。
使用.rvt 文件中的以下代码可以简单地重现该问题:
<?
proc dumbproc {} {
puts "this is dumbproc ([namespace current])"
}
oo::class create foo {
method bar {} {
puts "this is bar ([namespace current])"
dumbproc
}
}
set obj [foo new]
dumbproc
$obj bar
如果我只看代码,它似乎应该按预期工作,但实际上并没有,因为 Rivet 包的微妙行为和选择的特定配置。
在本例中,我使用了一个.rvt 文件,其代码在::request 命名空间内执行,因此dumbproc 过程的完全限定名称是::request::dumbproc。当在bar方法中调用名称解析算法时,它会在::oo::Obj12中搜索dumbproc,然后在::oo中,最后在::中,没有找到它并给出以下错误。
this is dumbproc (::request) this is bar (::oo::Obj16)
invalid command name "dumbproc"
while executing
"dumbproc"
(class "::request::foo" method "bar" line 3)
invoked from within
"$obj bar"
(in namespace eval "::request" script line 21)
invoked from within
"namespace eval request {
puts -nonewline ""
proc dumbproc {} {
puts "this is dumbproc ([namespace current])"
}
oo::class create..."
所以,Tcl 正确在做它所做的事情,一个特性。但是这种行为是不可预测的,因为当你编写一些类代码时,你必须知道它将被使用的上下文。
确实,如果我删除起始的 <? Rivet 魔法,将代码放入 test.tcl 文件并在交互式会话中使用它,我会得到同样的错误:
$ tclsh
% namespace eval ::myns {source test.tcl}
this is dumbproc (::myns)
this is bar (::oo::Obj12)
invalid command name "dumbproc"
我尝试通过将当前命名空间添加到类创建代码来解决问题
::oo::class create [namespace current]::foo { ... }
然后,我也尝试在命名空间内创建obj 对象
::oo::class create [namespace current]::foo { ... }
namespace eval [namespace current] {set obj [[namespace current]::foo new]}
然后,我切换到类的create 方法,为对象提供一个包含命名空间的限定名称
foo create [namespace current]::obj
obj bar
但一切都失败了。每次试验都表明,无论我如何做,TclOO 类中的方法总是在其对象唯一命名空间内执行。我错了吗?
有没有办法得到我想要的? TclOO 是否不打算以这种方式工作,在这种情况下为什么呢?真正让我惊讶的是这种依赖于上下文的行为,我不确定这是不是正确的事情,但也许我完全错了,并且有一些合理的案例,我错过了。
【问题讨论】:
标签: tcl