我找到了一些TclOO资源,提到你可以创建::oo::class
的子类。您也可以使用::oo::object create
创建裸对象,但不能从裸类迁移到真实类(即父oo::object
到父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
答案 0 :(得分: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命令。