具有继承/超类的TclOO变量范围

具有继承/超类的TclOO变量范围,tcl,scope,superclass,Tcl,Scope,Superclass,在用TclOO继承类时,我无意中发现了变量范围。 如果不重复声明,下面的成员变量nCrumbs对继承的类不可见 有没有办法避免复制超类中的所有变量声明 (我通读了所有的OO文档,特别是OO::define和OO::object,还有未导出的东西,都在谷歌上搜索过。有太多的概念可以绕过各种各样的东西,我迷路了。 我正在寻找使继承的类尽可能简单的东西。不过,超类中可能有任何奇特的复杂代码。) 任何帮助都将不胜感激,谢谢 oo::class create toaster { variable

在用TclOO继承类时,我无意中发现了变量范围。 如果不重复声明,下面的成员变量nCrumbs对继承的类不可见

有没有办法避免复制超类中的所有变量声明

(我通读了所有的OO文档,特别是OO::define和OO::object,还有未导出的东西,都在谷歌上搜索过。有太多的概念可以绕过各种各样的东西,我迷路了。 我正在寻找使继承的类尽可能简单的东西。不过,超类中可能有任何奇特的复杂代码。)

任何帮助都将不胜感激,谢谢

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