2

我想控制对 Itcl 公共变量的读取访问。我可以使用以下方法进行写访问:

package require Itcl
itcl::class base_model_lib {
    public variable filename ""
}
itcl::configbody base_model_lib::filename {
    puts "in filename write"
    dict set d_model filename $filename
}

configbody 定义了调用 config 时会发生什么$obj configure -filename foo.txt:但是我如何控制读取过程中发生的事情呢?想象一下,我想做的不仅仅是在读取过程中查找一个值。

我想继续使用标准的 Itcl 模式,即使用 cget/configure 向用户公开这些。

这就是我的问题。但是,让我描述一下我真正想做的事情,然后你告诉我是否应该做一些完全不同的事情:)

我喜欢python类。我喜欢我可以创建一个变量并从实例外部读取/写入它。稍后,当我想变得花哨时,我将创建方法(使用@property@property.setter)来自定义读/写,而用户不会看到 API 更改。我正在尝试在这里做同样的事情。

我的示例代码还建议了我想做的其他事情。实际上,文件名内部存储在字典中。我不想将整个字典暴露给用户,但我确实希望他们能够更改该字典中的值。所以,真正的“文件名”只是一个存根。我不想要一个叫做那个的公共变量。相反,我想使用 cget 和 configure 来读取和写入“事物”,我可能会选择创建一个简单的公共变量,或者可能希望定义一个查找它的过程。

PS:我确信我可以创建一个采用一个或两个参数的方法。如果一个,它的读取和两个它的写入。我认为这不是要走的路,因为我认为您不能使用 cget/configure 方法。

4

1 回答 1

3

所有 Itcl 变量都映射到名称难以猜测的名称空间中的 Tcl 变量。这意味着每当您通过 Tcl 的标准跟踪机制读取变量时(它发生在实际读取变量之前),您都可以获得回调;您需要做的就是在构造函数中创建跟踪。这需要使用itcl::scope并且最好使用,itcl::code $this以便我们可以使回调成为私有方法:

package require Itcl
itcl::class base_model_lib {
    public variable filename ""
    constructor {} {
        trace add variable [itcl::scope filename] read [itcl::code $this readcallback]
    }
    private method readcallback {args} {         # You can ignore the arguments here
        puts "about to read the -filename"
        set filename "abc.[expr rand()]"
    }
}

所做的一切itcl::configbody实际上等同于变量写入跟踪,这更常见一些,尽管我们通常更喜欢你现在直接设置跟踪,因为这是一种更通用的机制。运行上述脚本后演示:

% base_model_lib foo
foo
% foo configure
about to read the -filename
{-filename {} abc.0.8870089169996832}
% foo configure -filename
about to read the -filename
-filename {} abc.0.9588680136757288
% foo cget -filename
about to read the -filename
abc.0.694705847974264

如您所见,我们通过标准机制精确控制读取的内容(在这种情况下,一些随机变化的乱码,但您可以做得更好)。

于 2015-06-18T09:02:31.330 回答