0

のサブクラスを作成できると言及している 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
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 に答える