【发布时间】:2017-01-18 15:51:50
【问题描述】:
在 Ruby 中,可以为同一类的实例共享一个变量(静态)。即,所有人都看到相同的值,并且可以更改它。它可以节省内存,还可以带来其他好处。这也可以在 Perl、C++ 等中实现。对于 8.6 版,我如何在 Tcl OO 中实现相同的功能?
谢谢。
【问题讨论】:
在 Ruby 中,可以为同一类的实例共享一个变量(静态)。即,所有人都看到相同的值,并且可以更改它。它可以节省内存,还可以带来其他好处。这也可以在 Perl、C++ 等中实现。对于 8.6 版,我如何在 Tcl OO 中实现相同的功能?
谢谢。
【问题讨论】:
由于 TclOO 旨在成为简单的框架,因此需要一些脚本来实现结果。 tcllib 中的oo::util 包提供了必要的代码。
【讨论】:
要使类范围的变量对实例正确可见,需要三个步骤。
如果您能够处理开始时未设置的变量,则无需对此做太多事情。有些代码可以,有些不能。
oo::class create Example {
self variable foo
self method init {} {
set foo 123
}
}
Example init
我们的例子只有一个。请注意,我必须也在这里说variable;它与上面的self variable 具有不同的范围。 (实例与类)
oo::define Example {
variable foo
method bar {} {
incr foo
puts "foo is $foo"
}
}
这是一个棘手的问题。
oo::define Example {
constructor {} {
# Get the class's own private object namespace, where it keeps its own variables
set ns [info object namespace [self class]]
# Link the instance variable to the class variable; 'my eval' uses right context
# You can rename the variable here; see 'namespace upvar' docs for details
my eval [list namespace upvar $ns foo foo]
}
}
有了这三个,我们可以制作一些实例并尝试一下:
set e1 [Example new]
set e2 [Example new]
$e1 bar; # ==> foo is 124
$e1 bar; # ==> foo is 125
$e2 bar; # ==> foo is 126
$e2 bar; # ==> foo is 127
请注意,这是通过将 实例的命名空间 中的变量链接 到类的命名空间。此链接在此处使用 namespace upvar 完成,这是您以前可能从未使用过的命令。也可以使用upvar 命令来完成,尽管这种方法效率较低。
看起来有点不同,但做的事情是一样的:
oo::class create Example {
self {
variable foo
method init {} {
set foo 123
}
}
variable foo
constructor {} {
set ns [info object namespace [self class]]
my eval [list namespace upvar $ns foo foo]
}
method bar {} {
incr foo
puts "foo is $foo"
}
}
Example init
set e1 [Example new]
set e2 [Example new]
$e1 bar; # ==> foo is 124
$e1 bar; # ==> foo is 125
$e2 bar; # ==> foo is 126
$e2 bar; # ==> foo is 127
【讨论】:
self { ...} 行为的文档在哪里 - 我看到的只是用于自省的特定子命令 (tcl.tk/man/tcl/TclCmd/self.htm),以及 2) 代码似乎在没有 @987654332 的情况下工作@ - 虽然显然值从 1 开始,因为没有要调用的 Init。