假设以下代码声明:
itcl::class ObjectA {
private variable m_ownedObject
private variable m_someVariable
constructor {} \
{
set m_ownedObject [ObjectA #auto]
}
protected method SetSomeVariable {newVal} {
set m_someVariable $newVal
}
public method SomeMethod{} {
$m_ownedObject SetSomeVariable 5
}
}
这是我知道如何在m_ownedObject上从m_someVariable
内修改SomeMethod
的唯一方法。在其他语言中(比如说C / C ++ / C#/ Java),我很确定我可以这样说:
m_ownedObject.m_someVariable = 5
有没有办法在tcl中做这样的事情,还是我总是需要创建受保护的getter和setter?希望这是相当清楚的。
答案 0 :(得分:2)
$m_ownedObject configure -m_someVariable 5
答案 1 :(得分:1)
如果您将变量声明为私有,则意味着只能从类中访问该变量。这对C / C ++ / Java也有效......所以我不确定你的期望是什么。
无论如何,Tcl是一种动态语言,所以你可以这样做。
itcl::class tclass {
foreach v {time distance} {
method get$v {} [subst -nocommands { return [subst $$v] }]
method set$v nuval [subst -nocommands { set $v \$nuval } ]
protected variable $v "Var $v"
}
}
它会创建您需要的所有getters
和setters
;)
您可以在此处找到更多信息:http://wiki.tcl.tk/17667
答案 2 :(得分:1)
你不能直接在itcl中做你想要的。但是,这是Tcl,您可以解决这个问题,并直接从任何地方设置成员变量。我使用一个名为memv
的辅助例程,它传递一个实例和一个变量名,然后返回该变量的“引用”。
这显然绕过了Itcl设置的私有/受保护机制,因此您违反了使用它们的抽象。无论你想使用它,都是你的电话。我发现它对于调试非常有用,但在生产代码中却没有。
示例用法是:
set [memv m_ownedObject m_someVariable] 5
memv
的代码是:
proc memv {obj varname} {
# have to look up the variable, which might be in a base class
# so do 'info variable' to get that, and the full name is the 3rd element
# next two lines handle pulling apart an array
set aindex ""
regexp -- {^(.+)\((.+)\)$} $varname ignore varname aindex
set var [lindex [$obj info variable $varname] 2]
if {$aindex == ""} {
return [list @itcl $obj $var]
} else {
return [list @itcl $obj $var\($aindex\)]
}
}
同样,我有一个名为memv
的辅助例程,它允许您调用任何方法(包括私有和受保护的方法)。它的用法类似
[memf m_ownedObject SetSomeVariable] 5
它的代码是:
proc memf {obj fcnname} {
set f [$obj info function $fcnname]
if {[llength $f] != 5} {
error "expected '$obj info function $fcnname' to return something like 'private proc ::namespace::name args {...}' but got: $f"
}
set fullname [lindex [$obj info function $fcnname] 2]
set namespace [namespace qualifiers $fullname]
set function [namespace tail $fullname]
return [itcl::code -namespace $namespace $obj $function]
}