如何从 Tcl 的超类中访问派生的 类 成员变量?

How does one access a derived classes member variables from within the superclass in Tcl?

代码:

package require TclOO

oo::class create Supe {
    variable cape boots

    constructor {} {
        puts -nonewline "Supe: "
        puts [info class variables [self class]]
    }
}

oo::class create Clark {
    superclass Supe

    variable glasses suit

    constructor {} {
        puts -nonewline "Clark: "
        puts [info class variables [self class]]
        next
    }
}

set hero [Clark new]

输出:

Clark: glasses suit
Supe: cape boots

是否可以从 Supe 的构造函数中获取 Clark 的成员变量列表而不将它们作为参数传递给 Supe?

最终,目标是从 dict 参数动态设置派生的 class 变量:

foreach {varName} [info class variables [self class]] {
    variable $varName [dict get $args $varName]
}

如果上面的代码可以在superclass构造函数中使用,就可以避免将它放在每个派生的class构造函数中。

您可以使用 self objectself 获取对象的名称。然后,您可以使用 info object class 获取对象的 class。最后,你可以用 info class variables.

得到一个 class 的成员变量

将所有内容放在一起得出:

[info class variables [info object class [self]]]

我的看法并没有增加已经给出的答案,而是着眼于 OP 的激励问题:

Ultimately, the goal is to dynamically set derived class variables from a dict argument:

我过去一直使用的批量更新对象状态的方法是……。沿着:

oo::class create C {
  variable a b
  constructor {aDict} {
    my variable {*}[lsort -unique [my lookupVars [info object class [self]]]]
    # dict with aDict {;}
    lassign [dict values $aDict] {*}[dict keys $aDict]
  }

  method lookupVars {currentClass} {
    set v [info class variables $currentClass]
    foreach scl [info class superclasses $currentClass] {
      if {$scl eq "::oo::object"} {
        break
      }
      lappend v {*}[my lookupVars $scl]
    }
    return $v
  }

  method print {} {
    foreach v [info object vars [self]] {
      my variable $v
      puts "<$v> [set $v]"
    }
  }
}

关键项目是:

  • lookupVars 是一个自然递归的实现,遍历 class、直接和间接超级 classes 以收集定义的每个 class 变量。这是 Donal 描述的 "properties" 发现的后续。请注意,这在几个方面受到限制(例如,mixins 被忽略,TclOO 的内部线性化方案也没有反映,没有控制重复等)
  • lassign 可用于一次设置多个变量。或者,但有一些副作用,dict with "loads" a given dict's content into variables available for the current scope. my variable ?varName ...? 将提供方法本地链接到收集的每个 class 变量。这样,您可以保存脚本级循环,而不必为不匹配的键过滤提供的字典。

观看:

oo::class create D {
  superclass C
  variable c d
}

oo::class create E {
  superclass D
  variable e f
}


[D new {a 1 b 2 c 3 d 4}] print
[E new {a 1 b 2 c 3 d 4 f 5 e 8 x 3}] print
[D new {a 1 b 2 c 3 d 4 f 5 x 3}] print