2010-02-04 2 views
0

Предположим следующие объявления кода:Tcl: Настройка частной переменной экземпляра, принадлежащего в пределах класса

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_someVariable изнутри SomeMethod на m_ownedObject. На других языках (скажем, C/C++/C#/Java, чтобы назвать несколько), я уверен, что я мог бы просто сказать что-то вроде:

m_ownedObject.m_someVariable = 5 

Есть ли способ сделать что-то подобное в Tcl, или мне всегда нужно создавать защищенные геттеры и сеттеры? Надеюсь, это достаточно понятно.

ответ

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] 
} 
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

+0

Я не уверен, что вы поняли. Я получаю доступ к переменной из класса - я просто использую другой экземпляр (т. Е. Не «это»). Это разрешено на других языках. Я на 100% уверен в этом. Я просто проверил его на C# – Jordan