2

代码:

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 参数动态设置派生类变量:

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

如果上面的代码可以用在超类的构造函数中,就可以避免把它放在每个派生类的构造函数中。

4

2 回答 2

2

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

将它们放在一起会导致:

[info class variables [info object class [self]]]
于 2019-12-01T10:37:37.950 回答
2

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

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

我过去用来批量更新对象状态的东西是……。沿着:

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是一个自然递归的实现,遍历类、直接和间接超类以收集已定义的每类变量。这是对多纳尔所说的“属性”的发现的后续。请注意,这在几个方面受到限制(例如,mixin 被忽略,TclOO 的内部线性化方案也没有反映,没有对重复的控制等)
  • lassign可用于一次设置多个变量。或者,但有一些副作用,dict with将给定 dict 的内容“加载”到当前范围可用的变量中。my variable ?varName ...?将为收集的每个类变量提供方法本地链接。这样,您可以保存脚本级别的循环,并且不必为不匹配的键过滤提供的 dict。

手表:

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
于 2019-12-03T14:58:11.687 回答