【问题标题】:shared variable for class instances in TclTcl 中类实例的共享变量
【发布时间】:2017-01-18 15:51:50
【问题描述】:

在 Ruby 中,可以为同一类的实例共享一个变量(静态)。即,所有人都看到相同的值,并且可以更改它。它可以节省内存,还可以带来其他好处。这也可以在 Perl、C++ 等中实现。对于 8.6 版,我如何在 Tcl OO 中实现相同的功能?
谢谢。

【问题讨论】:

    标签: oop static tcl


    【解决方案1】:

    由于 TclOO 旨在成为简单的框架,因此需要一些脚本来实现结果。 tcllib 中的oo::util 包提供了必要的代码。

    【讨论】:

    • 我们最终可能会在 TclOO 的核心中添加更多的类变量和类方法支持。不过,现在这对我来说并不是一个重要的优先事项,尤其是对于类方法(在相关类对象上创建 self 方法可以提供 99% 的有用效果)。
    【解决方案2】:

    要使类范围的变量对实例正确可见,需要三个步骤。

    第一步:在类中设置一个值:

    如果您能够处理开始时未设置的变量,则无需对此做太多事情。有些代码可以,有些不能。

    oo::class create Example {
        self variable foo
        self method init {} {
            set foo 123
        }
    }
    Example init
    

    第 2 步:为将访问变量的实例定义一些方法

    我们的例子只有一个。请注意,我必须在这里说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
    

    【讨论】:

    • 两个问题:1) self { ...} 行为的文档在哪里 - 我看到的只是用于自省的特定子命令 (tcl.tk/man/tcl/TclCmd/self.htm),以及 2) 代码似乎在没有 @987654332 的情况下工作@ - 虽然显然值从 1 开始,因为没有要调用的 Init
    猜你喜欢
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 2020-04-16
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多