Tcl对象方法称为变量

时间:2019-12-23 18:30:02

标签: tcl

如何将对象方法作为变量执行?

oo::class create handlerTest {
    method onEvent {} {
        puts "onEvent method"
    }
}

set testObj [handlerTest new]
#set wrapper {$testObj onEvent}
#set wrapper {$testObj::my onEvent}
#set wrapper [namespace code {$testObj onEvent}]
#set wrapper "eval testObj onEvent
#set wrapper {[eval testObj onEvent]}
$wrapper

以上所有尝试似乎都是将$wrapper作为单个命令而不是带有args的命令来执行。

当我使用一个调用已定义包装器的外部库时,我无法更改包装器的调用方式(即{*}$wrapper)。

有没有办法做到这一点?

3 个答案:

答案 0 :(得分:2)

或者:

proc theWrapper {} [
    upvar 1 testObj testObj
    tailcall $testObj onEvent
}
set wrapper theWrapper
$wrapper

答案 1 :(得分:0)

重写命令名称本身的唯一方法是通过未知的处理程序(默认为在全局命名空间中称为unknown;您可能想使用该默认名称)。执行此操作时需要格外小心,因为默认处理程序会执行某些代码需要提供的操作;使用rename进行一些改组应该可以解决问题。

# only want special treatment for some commands
set autoexpanded [list $testObj]

# save for later
rename unknown _original_unknown

proc unknown args {
    global autoexpanded
    # if we want to expand the first word...
    if {[catch {lindex $args 0 0} cmd] == 0 && $cmd in $autoexpanded} {
        # delegate to the expanded command (tailcall is perfect here)
        set args [lassign $args cmd]
        tailcall {*}$cmd {*}$args
    } else {
        # delegate to the original unknown
        tailcall _original_unknown {*}$args
    }
}

请注意,这不是一种快速的分发机制。仅当其他唯一的选择因为该命令不存在而引发错误时才使用该命令(该命令也很慢,但是错误路径从来都不是最优的或没有优化的)。

答案 2 :(得分:0)

想到的最简单的方法是为别名生成一个名称,并将其放入变量中:

set testObj [handlerTest new]
set wrapper [interp alias {} wrapper[incr wrapperid] {} $testObj onEvent]
$wrapper

=> onEvent方法