具有继承/超类的 TclOO 变量范围 [英] TclOO Variable Scope with Inheritance/superclass

查看:49
本文介绍了具有继承/超类的 TclOO 变量范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在用 TclOO 继承类时偶然发现了变量作用域.下面的成员变量 nCrumbs 在不重复声明的情况下对继承的类是不可见的.

I stumbled over the variable scope when inheriting a class with TclOO. The member variable nCrumbs below is not visible to the inherited class without repeating the declaration.

有没有办法避免从超类复制所有变量声明?

Is there a way to avoid replicating all the variable declarations from the superclass?

(我通读了所有 OO 文档,特别是 oo::define 和 oo::object,还有非导出的东西,用谷歌搜索.有很多概念可以解决各种问题,我迷路了.我正在寻找使继承的类尽可能简单的东西.不过,超类中可能有任何花哨的复杂代码.)

(I read through all the OO documentation, specifically oo::define and oo::object, also the non-exported stuff, googled for it. There are so many concepts to get around various things, I got lost. I am looking for something that keeps the inherited class as simple as possible. The superclass may have any fancy complicated code in it, though.)

非常感谢任何帮助,谢谢.

Any help would be greatly appreciated, thanks.

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

推荐答案

该变量在物理上位于对象实例的私有命名空间中(如果你可以这么说代码的话).通过在声明中执行 variable,您可以指示方法绑定仅使其可用而无需进一步的命令.

The variable is physically located (if you can say that for code) in a private namespace for the object instance. By doing variable in the declaration, you are directing the method bindings to merely make it available without further commands.

但是是的,子类也必须使用 variable 来默认查看它,或者使用标准的 Tcl 变量范围管理命令之一,例如 upvarnamespace upvar,甚至是私有的 variable method.

But yes, subclasses have to use variable as well to see it by default, or to use one of the standard Tcl variable scope management commands, e.g., upvar or namespace upvar, or even the private variable method.

oo::class create smartToaster {
    superclass toaster
    method toast {nSlices} {
        my variable nCrumbs
        if {$nCrumbs > 40} {
            my clean
        }
        next $nSlices
    }
}

oo::class create smartToaster {
    superclass toaster
    method toast {nSlices} {
        namespace upvar [namespace current] nCrumbs nc
        if {$nc > 40} {
            my clean
        }
        next $nSlices
    }
}

以前不是这样的,但发现其他方式太混乱了;类的变量声明仅影响该类的方法,而不影响其子类.

It didn't used to be that way, but it was found to be just too confusing otherwise; the variable declarations for a class only affect the methods of that class, not its subclasses.

:可以通过适当的元类魔法使父变量在子变量中也可见:

: It is possible to make a parent's variables also visible in the child via appropriate metaclass magic:

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 类).

While I don't in general recommend this as it makes a subclass much more fragile when a superclass evolves, and it doesn't track any changes to the superclass, it's easy to set up with a little scripting. You just delegate the smartness to your own metaclass and use that to construct all your operational classes (which are purely conventional TclOO classes from there on).

这篇关于具有继承/超类的 TclOO 变量范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆