为了增强tcl/tk
程序的功能,我想重新实现其中一个原始(命名空间)函数。新的实现应该调用核心功能的原始实现,并添加一些漂亮的东西。
记录得很清楚using tcl's rename
command。
为了尽可能保持模块化,我想将我的新功能放在一个单独的命名空间中。
我还想避免在toobe-enhanced函数的原始命名空间中添加内容。
所以计划是:
::simple::function
重命名为::enhanced::simple_function
::simple::function
::enhanced::simple_function
这非常有效,除非原始函数使用其命名空间的其他成员而没有完全限定它们。
以下是一个例子:
namespace eval ::foospace:: {
proc bar {a} { puts $a }
proc foo {X} { bar "foospace:foo:: $X" }
}
## test original function
::foospace::foo "hello world"
## shadowing the original ::foospace::foo into a new namespace
rename ::foospace::foo ::barspace::foo
proc foospace::foo {x} {
puts "DEBUG: $x"
::barspace::foo "$x"
}
# test enhanced function
::foospace::foo "goodbye moon"
这给了我:
invalid command name "bar" while executing "bar "foospace:foo:: $X" "
如果原始::foospace::foo
使用::foospace::bar
而非bar
,则一切正常。
不幸的是,我无法“修复”原始实现。
如果我只是将::foospace::foo
重命名为::foospace::foo_bar
而不是::barspace::foo
,这也会有效,但这意味着要触及不属于我的命名空间(我我想避免)。
有没有办法将原始函数重命名为新的命名空间,并在原始函数中允许不合格的函数名?
答案 0 :(得分:1)
有关过程和命名空间的一个原因是,用于过程的命令和变量解析的当前命名空间由放置过程的命名空间决定。这意味着当您rename
时将过程放入另一个命名空间,您可以更改其行为方式。当大多数命令都在全局命名空间中时(如果Tcl搜索它是否能够在当前命名空间中找到命令),你大多数都会逃脱它,但它可以产生非常深远的影响。可以将代码与移动的影响隔离开来(例如,使用完全限定的命令名称和namespace upvar
而不是variable
)但是大多数人都不会打扰这是一种几乎不需要的巨大痛苦。
建议您不要在名称空间中重命名。它会导致难以调试的麻烦(我可以根据具体情况来解释它们);您已经看到的问题就是这个问题,不,您无法将原始函数重命名为新的命名空间,并允许原始函数中的非限定函数名称。
还有其他技巧。命令执行跟踪可能是合适的,就像使用命名空间导入一样。或者可能是你正在尝试做一个伪对象系统:如果是这样的话,你应该切换到一个真实的,因为他们处理很多问题你没有想到。 (我最喜欢的是TclOO,它是Tcl 8.6的一部分,但后来我写了它,所以我有点偏见!)使用真实的对象系统可以使事情变得更加简单。