我想控制对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
。但是如何控制阅读过程中发生的事情呢?想象一下,我想做的不仅仅是在阅读过程中查找一个值。
我想继续使用使用cget / configure的标准Itcl模式向用户公开这些模式。
这是我的问题。但是,让我描述一下我真正想做的事情,你告诉我是否应该做一些完全不同的事情:)
我喜欢python类。我喜欢我可以创建一个变量并从实例外部读/写它。稍后,当我想要开心时,我将创建方法(使用@property
和@property.setter
)来自定义读/写,而无需用户看到API更改。我想在这里做同样的事情。
我的示例代码也提出了我想做的其他事情。实际上,文件名内部存储在字典中。我不想将整个字典暴露给用户,但我希望他们能够更改该字典中的值。所以,真正的'文件名'只是一个存根。我不想要一个名为的公共变量。我反而想使用cget和configure来读取和写一个“东西”,我可以选择制作一个简单的公共变量,或者可能希望定义一个查找过程。
PS:我确信我可以创建一个带有一个或两个参数的方法。如果一个,它的读取和两个写入。我认为不是那种方式,因为我不认为你可以使用cget / configure方法。
答案 0 :(得分:3)
所有Itcl变量都映射到名称很难猜到的名称空间中的Tcl变量。这意味着只要您通过Tcl的标准跟踪机制读取变量(它在变量实际读取之前发生)就可以获得回调;您需要做的就是create the trace in the constructor。这需要使用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
正如您所看到的,我们正在准确控制通过标准机制读取的内容(在这种情况下,一些随机变化的乱码,但您可以做得更好)。