如何将对象方法作为变量执行?
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
)。
有没有办法做到这一点?
答案 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方法