0

我发现一些 TclOO 资源提到您可以创建::oo::class. 您也可以使用 创建裸对象::oo::object create,但不能从裸类迁移到真实类(即 parentoo::object到 parent oo::class

我正在寻找一个用于定义模块的 DSL,它只是创建类定义。

module create mysql 5.5 {
  executable mysqld
  method post_install { ... }
}

module create redis 2.6 {
  executable redis-server
  ...
}

然后这些可以用作

set mod [mysql new]
$mod install
$mod post_install
4

1 回答 1

1

虽然您无法直接在oo::define系统中创建特定于类的扩展命令,但您可以非常轻松地完成次优任务。诀窍是namespace path仅在定义处理期间将附加命令配置到命名空间。说元类构造函数很容易做这种事情,这有点过分了:

# First, build the definition of the extensions
namespace eval ::ModuleDefineExtensions {
    proc executable {program} {
        # I'm not quite sure how you want to handle this, but [uplevel] and
        # [info level] will reveal what you need.
        puts "define executable as $program here"
    }
}

# Now, the [module] metaclass
oo::class create module {
    superclass oo::class
    constructor {definitionScript} {
        # Save the old path
        set oldpath [namespace eval ::oo::define {namespace path}]

        # Set the new one
        namespace eval ::oo::define {namespace path ::ModuleDefineExtensions}

        # Now let the superclass constructor handle this, trapping errors
        catch {next $definitionScript} msg opt

        # Restore the old path
        namespace eval ::oo::define [list namespace path $oldpath]

        # Rethrow any errors
        return -options $opt $msg
    }
}

您可能需要更多零碎的东西(例如,定义通用方法的合适的默认模块类超类),但这些都是常规的。


如果您使用的是 8.6,则module定义可以更简单(这次没有注释):

oo::class create module {
    superclass oo::class
    constructor {definitionScript} {
        set oldpath [namespace eval ::oo::define {namespace path}]
        namespace eval ::oo::define {namespace path ::ModuleDefineExtensions}
        try {
            next $definitionScript
        } finally {
            namespace eval ::oo::define [list namespace path $oldpath]
        }
    }
}

原理上是一样的,只是使用了8.6的try/finally命令。

于 2012-12-04T00:07:03.697 回答