Tcl:设置类中拥有的实例的私有变量

发布于 2024-08-19 22:43:41 字数 644 浏览 10 评论 0原文

假设有以下代码声明:

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 上的 SomeMethod 内修改 m_someVariable 的唯一方法。在其他语言中(例如 C/C++/C#/Java 等),我很确定我可以这样说:

m_ownedObject.m_someVariable = 5

有没有办法在 tcl 中做这样的事情,或者我总是需要创建 protected getter 和 setter?希望这是相当清楚的。

Suppose the following code declarations:

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

This is the only way I know how to modify m_someVariable from within SomeMethod on m_ownedObject. In other languages (say C/C++/C#/Java to name a few), I'm pretty sure I could just say something like:

m_ownedObject.m_someVariable = 5

Is there a way to do something like this in tcl, or do I always need to create protected getters and setters? Hopefully this is reasonably clear.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲鸠 2024-08-26 22:43:41

您不能直接执行您在 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]
}

You cannot directly do what you're asking for in itcl. However, this being Tcl, you can work around that, and directly set the member variable from anywhere. I use a helper routine called memv which you pass an instance and a variable name, and it returns a "reference" to that variable.

This obviously bypasses the private/protected mechanisms that Itcl set up, so you're violating abstractions using them. It's your call whether you want to use it. I find it invaluable for debugging, but don't it in production code.

The example usage is:

set [memv m_ownedObject m_someVariable] 5

The code for memv is:

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

Similarly, I have a helper routine named memv which allows you to call any method (including private and protected methods). It's usage is similar

[memf m_ownedObject SetSomeVariable] 5

And it's code is:

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]
}
埋情葬爱 2024-08-26 22:43:41
$m_ownedObject configure -m_someVariable 5
$m_ownedObject configure -m_someVariable 5
海螺姑娘 2024-08-26 22:43:41

如果您将变量声明为私有,则意味着只能从类内部访问该变量。这对于 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"
      }
  }

它将创建您需要的所有 getterssetters ;)

您可以在此处找到更多信息:http://wiki.tcl.tk/17667

If you're declaring a variable as private, means that can be only accessed from within the class. And that's also valid for C/C++/Java ... so I'm not sure what are you expecting.

Anyway Tcl is a dynamic language, so you can do something like that.

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

And it will create all the getters and setters that you need ;)

You can find more info here: http://wiki.tcl.tk/17667

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文