具有继承/超类的TclOO变量范围
在用TclOO继承类时,我无意中发现了变量范围。 如果不重复声明,下面的成员变量nCrumbs对继承的类不可见 有没有办法避免复制超类中的所有变量声明 (我通读了所有的OO文档,特别是OO::define和OO::object,还有未导出的东西,都在谷歌上搜索过。有太多的概念可以绕过各种各样的东西,我迷路了。 我正在寻找使继承的类尽可能简单的东西。不过,超类中可能有任何奇特的复杂代码。) 任何帮助都将不胜感激,谢谢具有继承/超类的TclOO变量范围,tcl,scope,superclass,Tcl,Scope,Superclass,在用TclOO继承类时,我无意中发现了变量范围。 如果不重复声明,下面的成员变量nCrumbs对继承的类不可见 有没有办法避免复制超类中的所有变量声明 (我通读了所有的OO文档,特别是OO::define和OO::object,还有未导出的东西,都在谷歌上搜索过。有太多的概念可以绕过各种各样的东西,我迷路了。 我正在寻找使继承的类尽可能简单的东西。不过,超类中可能有任何奇特的复杂代码。) 任何帮助都将不胜感激,谢谢 oo::class create toaster { variable
oo::class create toaster {
variable nCrumbs; #declaration
constructor {} {
set nCrumbs 0; #definition
}
method toast {nSlices} {
if {$nCrumbs > 50} {
error "== FIRE! FIRE! =="
}
set nCrumbs [expr $nCrumbs+4*$nSlices]
}
method clean {} {
set nCrumbs 0
}
}
oo::class create smartToaster {
superclass toaster; #inherit
variable nCrumbs; #<======= have to declare again
method toast {nSlices} {
if {$nCrumbs > 40} {
my clean
}
next $nSlices; #call superclass method
}
}
set clsToaster [smartToaster new]
$clsToaster toast 2
oo::类创建烤面包机{
变量nCrumbs;#声明
构造函数{}{
设置nCrumbs 0;#定义
}
方法toast{nSlices}{
如果{$nCrumbs>50}{
错误“==开火!开火!==”
}
设置nCrumbs[expr$nCrumbs+4*$nSlices]
}
方法clean{}{
设置nCrumbs 0
}
}
oo::类创建smartToaster{
超类烤面包机;#继承
变量nCrumbs;#40}{
我的干净
}
下一个$N许可证#调用超类方法
}
}
设置clsToaster[智能烤面包机新版本]
$clsToaster吐司2
变量在物理上位于对象实例的私有名称空间中(如果对于代码可以这样说的话)。通过在声明中执行variable
,可以指导方法绑定仅使其可用,而无需进一步的命令
但是,默认情况下,子类也必须使用变量
,或者使用标准的Tcl变量范围管理命令之一,例如upvar
或名称空间upvar
,甚至是私有的变量
方法
过去不是这样的,但人们发现在其他方面它太令人困惑了;类的变量声明只影响该类的方法,而不影响其子类
[编辑]:可以通过适当的元类魔术使父变量在子变量中也可见:
oo::class create Class {
superclass oo::class
constructor args {
next {*}$args
set cs [info class superclasses [self]]
while {[llength $cs]} {
set cs [concat [lassign $cs c] [info class superclasses $c]]
oo::define [self] variable -append {*}[info class variables $c]
}
}
}
证明这一点:
% Class create foo {
variable x
}
::foo
% Class create bar {
superclass foo
variable y
}
::bar
% Class create boo {
superclass bar
variable z
}
::boo
% info class variables boo
z y x
虽然我一般不建议这样做,因为当超类进化时,它会使子类变得更加脆弱,并且不会跟踪对超类的任何更改,但只需编写一点脚本就可以轻松设置。您只需将智能委托给您自己的元类,并使用它来构造所有的操作类(从那时起就是纯传统的TclOO类)。Donal,感谢您的回答 因此,我假设默认情况下没有机制使所有超类变量可用 我目前的解决方案是收集所有变量名,然后通过一次调用声明它们。 然而,我必须在每种方法中重复这一点。我想把declareSuperclassVars放在方法之外。 这有可能吗?也许用另一种方法 谢谢
oo::class create toaster {
variable nCrumbs; #declaration
variable toTest; #another one nowhere defined
constructor {} {
set nCrumbs 0; #definition
}
method toast {nSlices} {
if {$nCrumbs > 50} {
error "== FIRE! FIRE! =="
}
set nCrumbs [expr $nCrumbs+4*$nSlices]
}
method clean {} {
set nCrumbs 0
}
method declareSuperclassVars {} {
my variable lSuperclassVars
set lSuperclassVars [info vars]; #fill variable list
uplevel 1 {
my variable lSuperclassVars
eval "my variable $lSuperclassVars"
}
}
}
oo::class create smartToaster {
superclass toaster; #inherit
#declareSuperclassVars; #<======= would like to do it here
method toast {nSlices} {
my declareSuperclassVars; #declare all at once
if {$nCrumbs > 40} {
my clean
}
next $nSlices; #call superclass method
}
}
set clsToaster [smartToaster new]
$clsToaster toast 2
oo::类创建烤面包机{
变量nCrumbs;#声明
变量toTest;#另一个未定义的变量
构造函数{}{
设置nCrumbs 0;#定义
}
方法toast{nSlices}{
如果{$nCrumbs>50}{
错误“==开火!开火!==”
}
设置nCrumbs[expr$nCrumbs+4*$nSlices]
}
方法clean{}{
设置nCrumbs 0
}
方法declareSuperclassVars{}{
我的变量lSuperclassVars
设置lSuperclassVars[info vars];#填充变量列表
上一级{
我的变量lSuperclassVars
评估“我的变量$lSuperclassVars”
}
}
}
oo::类创建smartToaster{
超类烤面包机;#继承
#庄家优等股;#40}{
我的干净
}
下一个$N许可证#调用超类方法
}
}
设置clsToaster[智能烤面包机新版本]
$clsToaster吐司2
请参见我的文章编辑。我仍然认为这是个坏主意,但这是很有可能的。
% Class create foo {
variable x
}
::foo
% Class create bar {
superclass foo
variable y
}
::bar
% Class create boo {
superclass bar
variable z
}
::boo
% info class variables boo
z y x
oo::class create toaster {
variable nCrumbs; #declaration
variable toTest; #another one nowhere defined
constructor {} {
set nCrumbs 0; #definition
}
method toast {nSlices} {
if {$nCrumbs > 50} {
error "== FIRE! FIRE! =="
}
set nCrumbs [expr $nCrumbs+4*$nSlices]
}
method clean {} {
set nCrumbs 0
}
method declareSuperclassVars {} {
my variable lSuperclassVars
set lSuperclassVars [info vars]; #fill variable list
uplevel 1 {
my variable lSuperclassVars
eval "my variable $lSuperclassVars"
}
}
}
oo::class create smartToaster {
superclass toaster; #inherit
#declareSuperclassVars; #<======= would like to do it here
method toast {nSlices} {
my declareSuperclassVars; #declare all at once
if {$nCrumbs > 40} {
my clean
}
next $nSlices; #call superclass method
}
}
set clsToaster [smartToaster new]
$clsToaster toast 2