Class 我可以添加到::oo::define以添加全局tclOO类定义扩展,如何在非全局的情况下执行此操作?
我发现一些TclOO资源提到可以创建Class 我可以添加到::oo::define以添加全局tclOO类定义扩展,如何在非全局的情况下执行此操作?,class,tcl,Class,Tcl,我发现一些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 re
::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
虽然您不能直接在
oo::define
系统中生成特定于类的扩展命令,但您可以非常轻松地完成次优任务。诀窍是使用名称空间路径
在定义处理期间将附加命令配置到名称空间。这是一种有点过于花哨的说法,可以说元类构造函数很容易做到这一点:
# 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,
模块
的定义可以更简单(这次没有注释):
原则上是一样的,但是使用了8.6的try/finally命令。您不能将非类更改为类,也不能将非类更改为类,反之亦然(因为它们下面有不同的C结构),并且
oo::object
和oo::class
本身有固定的关系-其他一切都取决于它们但除了这些强制执行的限制外,你还可以在很大程度上改变周围的情况。你可以做的一些事情可能是不明智的,但是如果你需要的话,选择是存在的…
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]
}
}
}