クラス固有の拡張コマンドをシステムで直接作成することはでき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 コマンドを使用します。