首页 > 解决方案 > Tcl oo::class 中的 proc

问题描述

一个愚蠢的问题。我有一个 oo::class 并做了一件可怕的事情 - 包括 procs 到构造函数和方法中:

oo::class create MyClass {

    constructor {args} {
        proc silly {args} {
            puts "-------------silly's args: $args"
            puts namespace=[namespace current]
            set v [namespace current]::sillyvar
            puts $v=[incr $v]
            puts vars=[info vars [namespace current]::*]
        }
    }
    destructor {
        foreach proc {silly SILLY} {
            rename $proc ""
        }
    }
    method createprocs {} {
        proc SILLY {args} {
            puts "-------------SILLY's args: $args"
            set v [namespace current]::sillyvar
            puts $v=[incr $v]
        }
    }
    method another {} {
        silly ;# works ok
    }
}
MyClass create myobj
myobj createprocs
[info object namespace myobj]::silly hello world
myobj another
[info object namespace myobj]::SILLY HELLO WORLD
MyClass destroy

输出看起来不错:

-------------silly's args: hello world
namespace=::oo::Obj12
::oo::Obj12::sillyvar=1
vars=::oo::Obj12::sillyvar
-------------silly's args: 
namespace=::oo::Obj12
::oo::Obj12::sillyvar=2
vars=::oo::Obj12::sillyvar
-------------SILLY's args: HELLO WORLD
::oo::Obj12::sillyvar=3

各位好心人能说一下,对吗?如果是这样,它在哪里有用?

我刚才看到的是:

1) silly 和 SILLY 都被“输出”了。

2) 我不需要“my silly”和“[self] silly”来从对象访问 silly proc。

标签: ooptcl

解决方案


各位好心人能说一下,对吗?

对我来说它看起来不错,只是你不需要析构函数。这些过程是在对象实例的命名空间中创建的(这也是对象变量所在的位置,FWIW),并且在对象被销毁时会自动删除(反之亦然;你不能没有另一个)。

如果是这样,它在哪里有用?

我相当多地使用在方法和构造函数中创建的过程(和其他命令)。他们可以做一些事情,比如像 Tcl 的私有子语言等等(就像你可以将命令放在一个普通的命名空间中一样;它没有显着不同),所以这真的非常有用。它们也很容易委托给使用forwarded 方法。

更简单的技巧之一是在外部对象中创建一个子对象,并通过以下方式委托一些方法调用:

oo::class create Outer {
    constructor {} {
        Inner create inner [self]
        puts "created [self]"
    }
    destructor {
        puts "destroyed [self]"
    }
    method foo {} {
        puts "this is foo of [self]"
    }
    forward bar  inner foo
}
oo::class create Inner {
    constructor {outer} {
        puts "created [self] inside $outer"
    }
    destructor {
        puts "destroyed [self]"
    }
    method foo {} {
        puts "this is foo of [self]"
    }
}

证明这一点:

Outer create x
# ⇒ created ::oo::Obj13::inner inside ::x
# ⇒ created ::x
x foo
# ⇒ this is foo of ::x
x bar
# ⇒ this is foo of ::oo::Obj13::inner
x destroy
# ⇒ destroyed ::x
# ⇒ destroyed ::oo::Obj13::inner

这显示了工作中的遏制和委派(基于您的程序将使用的相同机制)。如您所见,inner在 的私有命名空间内创建x,并x bar通过路由到inner foo. 更好的是,whenx被销毁,完全inner没有特殊代码;这在复杂代码中非常有用。


推荐阅读