首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >upvar,TclOO,以及下一个解释(也许)意外行为

upvar,TclOO,以及下一个解释(也许)意外行为
EN

Stack Overflow用户
提问于 2021-02-15 02:02:14
回答 1查看 102关注 0票数 5

我想知道是否有人能解释为什么我可以成功地在嵌套TclOO中链接upvars的幕后细节,但是它不能在嵌套的方法中工作(这些方法在子类中被覆盖)。(有人告诉我,在TclOO类方法中调用next有点像“临时尾调用”,因为没有创建新的堆栈级别。是这个案子吗?如果是的话,全貌是什么?)

例如,以下三种方法并不都会产生相同的结果:

代码语言:javascript
复制
proc addone {varname} {
  upvar $varname x;
  incr x;
}
proc addanotherone {varname} {
  upvar $varname xx;
  addone xx;
  incr xx;
}

oo::class create C1 {
  method addone {varname} {
    upvar $varname x;
    incr x;
  }
}
oo::class create S1 {
   superclass C1;
   method addone {varname} {
      upvar $varname xx;
      next xx;
      incr xx;
   }
 }
 oo::class create S2 {
   superclass C1;
   method addone {varname} {
     upvar $varname xx;
     next $varname;
     incr xx;
   }
 }
 set s1 [S1 new];
 set s2 [S2 new];
 set y 1;
 addanotherone y;
 set y; # First result gives 3, as expected;
 set y 1;
 $s1 addone y;
 set y; # gives 2, unexpected;
 set y 1;
 $s2 addone y; 
 set y;  #gives 3, unexpected, because original varname seems to be "two levels" deep.

如果next以某种方式运行在相同的堆栈级别上,那么它能否在调用者作用域中创建变量而不使用"uplevel"?

如果不是的话,它并不是在同一水平上运行,那么它更像是一个闭包吗?

我对真正的细节感兴趣,比如它与尾盘、上行的使用,或者其他应该考虑的概念有什么不同。谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-15 08:39:09

next命令在内部有点像uplevel (特别是uplevel 1),因为它在运行超类实现时暂时删除调用next 的方法的堆栈帧,在next返回时恢复堆栈帧。

这意味着您可以重写超类中的方法,而不需要特别为此做准备的超类。对于Tcl来说,这是其他一些旧的对象系统的一个主要问题,您需要一个特殊的调用来获得upvaruplevel的深度参数,而且很容易忘记这一点,所以我更改了TclOO。但是,这种更改的直接后果意味着您在S1 » addone中所做的操作将无法工作;它将在调用范围内创建/覆盖一个附加变量xxS2 » addone是我认为是惯用的。

如果要在方法和它覆盖的方法之间传递一个内部变量(根据定义,这需要两者合作),则在对象的状态命名空间中使用一个变量;您的类对此有完全的控制。或者通过my[self]调用一个方法;这是一个标准的方法调用(包含所有的含义)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66201923

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档