snit2.2/1.3のマニュアルを勝手に日本語に翻訳したものです。ほとんど直訳
オリジナルの文書はhttp://tcllib.sourceforge.net/doc/snit.htmlです。



名前

snit -
Snit's Not Incr Tcl

コマンド概略

package require Tcl 8.5
package require snit  ? 2.2.1 ? 
snit::type name definition
typevariable name  ? -array ?   ? value ? 
typemethod name arglist body
typeconstructor body
variable name  ? -array ?   ? value ? 
method name arglist body
option namespec  ? defaultValue ? 
option namespec  ? options... ? 
constructor arglist body
destructor body
proc name args body
delegate method name to comp  ? as target ? 
delegate method name  ? to comp ?  using pattern
delegate method *  ? to comp ?   ? using pattern ?   ? except exceptions ? 
delegate option namespec to comp
delegate option namespec to comp as target
delegate option * to comp
delegate option * to comp except exceptions
component comp  ? -public method ?   ? -inherit flag ? 
delegate typemethod name to comp  ? as target ? 
delegate typemethod name  ? to comp ?  using pattern
delegate typemethod *  ? to comp ?   ? using pattern ?   ? except exceptions ? 
typecomponent comp  ? -public typemethod ?   ? -inherit flag ? 
pragma  ? options... ? 
expose comp
expose comp as method
onconfigure name arglist body
oncget name body
snit::widget name definition
widgetclass name
hulltype type
snit::widgetadaptor name definition
snit::typemethod type name arglist body
snit::method type name arglist body
snit::macro name arglist body
snit::compile which type body
$type typemethod args...
$type create name  ? option value ... ? 
$type info typevars  ? pattern ? 
$type info typemethods  ? pattern ? 
$type info args method
$type info body method
$type info default method aname varname
$type info instances  ? pattern ? 
$type destroy
$object method args...
$object configure  ? option ?   ? value ?  ...
$object configurelist optionlist
$object cget option
$object destroy
$object info type
$object info vars  ? pattern ? 
$object info typevars  ? pattern ? 
$object info typemethods  ? pattern ? 
$object info options  ? pattern ? 
$object info methods  ? pattern ? 
$object info args method
$object info body method
$object info default method aname varname
mymethod name  ? args... ? 
mytypemethod name  ? args... ? 
myproc name  ? args... ? 
myvar name
mytypevar name
from argvName option  ? defvalue ? 
install compName using objType objName args...
installhull using widgetType args...
installhull name
variable name
typevariable name
varname name
typevarname name
codename name
snit::boolean validate  ? value ? 
snit::boolean name
snit::double validate  ? value ? 
snit::double name  ? option value... ? 
snit::enum validate  ? value ? 
snit::enum name  ? option value... ? 
snit::fpixels validate  ? value ? 
snit::fpixels name  ? option value... ? 
snit::integer validate  ? value ? 
snit::integer name  ? option value... ? 
snit::listtype validate  ? value ? 
snit::listtype name  ? option value... ? 
snit::pixels validate  ? value ? 
snit::pixels name  ? option value... ? 
snit::stringtype validate  ? value ? 
snit::stringtype name  ? option value... ? 
snit::window validate  ? value ? 
snit::window name

説明

SnitとはピュアTclのオブジェクト、メガウィジェットシステムです。Tclオブジェクトシステムとしてはユニークな、継承でなく委譲ベースのオブジェクトシステムです。 一般的に、継承ベースのオブジェクトシステムでは、限定された同じシステムでの使用を前提に、定義されたクラスから継承ができるだけです。 Tclにとってオブジェクトとは、オブジェクトのように振舞う何かです。どのようにオブジェクトが実装されているかは問題とするべきではありません。Snitはこれらの材料を使って手軽にアプリケーションを構築することを目的としています。 従って、自前のオブジェクトであろうが、Tkウィジェットであろうが、IncrTclのオブジェクトであろうが、BWidgetであろうが、大体どんなオブジェクトでも組み込んだり構築できるようにSnitは設計されています。

このマニュアルはリファレンス用です。もっとチュートリアルやSnitの概念を知りたい時はsnitfaqを見てください。

Snitのバージョン

このマニュアルはSnit2.2とSnit1.3を対象にしています。この二つのバージョンの違いは単純です。Snit2.2はTcl8.5の新しい機能を使ったスピードの最適化を含んでいます。Snit1.3はTcl8.3、Tcl8.4、Tcl8.5の全てをサポートしています。 しかしながら、この二つにはいくつかのマイナーな違いがあります。これらの違いは、マニュアルにおいて"Snit 1.x 非互換"というラベルで区別しています。またsnitfaqでも述べています。

リファレンス

型とウィジェットの定義

Snitは新しい型を定義するための次のコマンドを提供します。

snit::widget定義ではsnit::type定義で使用可能なステートメントを含むことが出来ます。また、それに加えて次のものを含むこともできます。

型コマンド

型またはウィジェット定義は型コマンドを作成します。これはその型のインスタンスを作成するのに使われます。型コマンドの形式は次のようになっています。

標準的な型メソッド

型定義での型メソッドに加えて、全ての型とウィジェットコマンドは普通少なくとも次のサブコマンドを持っています。

インスタンスコマンド

Snitのtype、widgetの型メソッドcreateは、型のオブジェクトを生成します。 各オブジェクトは固有の名前を持っていて、その名前はまた、Tclのコマンドでもあります。このコマンドはオブジェクトのメソッドとデータにアクセスするのに使われます。次のような構文になります。

標準的なインスタンスメソッド

型定義で委譲されたインスタンスメソッド、ローカル定義されたインスタンスメソッドに加えて、全てのSnitオブジェクトは最低限次のサブコマンドも持ちます。

オブジェクトコード中で使用するコマンド

Snitは オブジェクトコード中で使用できる 次のコマンドを定義しています。つまり、型メソッド、インスタンスメソッド、コンストラクタ、デストラクタ、onconfigure処理、oncget処理、プロシージャにおいて使うことができます。このコマンドは::snit::名前空間中には存在せず、型とともに作成され、名前空間の装飾なしに使うことができます。

コンポーネントと委譲

オブジェクトが他のオブジェクトを含んでいる時、例えば、ツールバーがボタンを含んでいたり、GUIオブジェクトがデータベースを参照する他のオブジェクトを含んでいる場合、含まれたオブジェクトはコンポーネントと呼ばれます。Snitオブジェクトによって所有されているコンポーネントを取り扱う標準的な方法は、それらをcomponentを使って宣言することです。componentはコンポーネントのインスタンス変数を作成します。次の例では、dogオブジェクトはtailオブジェクトを所有しています。

snit::type dog {
    component mytail

    constructor {args} {
        set mytail [tail %AUTO% -partof $self]
        $self configurelist $args
    }

    method wag {} {
        $mytail wag
    }
}

snit::type tail {
    option -length 5
    option -partof
    method wag {} { return "Wag, wag, wag."}
}

tailオブジェクトの名前はインスタンス変数に保存されるので、簡単にメソッドにアクセスすることができます。

installコマンドは、コンポーネントの作成とインストールの別の方法を提供します。

snit::type dog {
    component mytail

    constructor {args} {
        install mytail using tail %AUTO% -partof $self
        $self configurelist $args
    }

    method wag {} {
        $mytail wag
    }
}

snit::typeにとっては、上記の二つの方法は同じです。snit::widgetsnit::widgetadaptorでは、installコマンドはTkオプションデータベースに問い合わせることでウィジェットのオプションを適切に初期化します。

上記の例ではdogオブジェクトのwagメソッドは、単純にtailコンポーネントのwagメソッドを呼び出していました。OO用語ではこれは委譲(デリゲーション)と呼ばれています。Snitは委譲するための簡単な方法を提供しています。

snit::type dog {
    delegate method wag to mytail

    constructor {args} {
        install mytail using tail %AUTO% -partof $self
        $self configurelist $args
    }
}

型宣言中のdelegate文は、暗黙的に、コンポーネントの名前を保存するためにインスタンス変数mytailを定義します。(とはいえ、componentを使って明示的にそれを宣言するのはよいことです。)そして、dogオブジェクトのwagメソッドを定義し、mytailコンポーネントに委譲します。

お望みならほかの未知のメソッドも全て、指定されたコンポーネントに委譲することができます。

snit::type dog {
    delegate method * to mytail

    constructor {args} {
        set mytail [tail %AUTO% -partof $self]
        $self configurelist $args
    }

    method bark { return "Bark, bark, bark!" }
}

この場合、dogオブジェクトはそれ自身のbarkメソッドを処理しますが、wagmytailにパスされるでしょう。dogにもtailにも存在していないメソッドの呼び出しは単純にエラーになります。

オプションの委譲はメソッドの委譲に似ていますが、Tkオプションデータベースと相互作用する点は異なります。

型コンポーネントと委譲

型コンポーネントとインスタンスコンポーネントの関係は、型変数とインスタンス変数の関係や、型メソッドとインスタンスメソッドの関係と同じです。ちょうどインスタンスコンポーネントがコマンド名を保持しているインスタンス変数であるように、型コンポーネントはコマンドの名前を保持している型変数です。要するに、型コンポーネントとは、 その型の全てのインスタンスで共有されるコンポーネントのことです。

コンポーネントと委譲で説明したとおり、delegate methodをインスタンスコンポーネントにメソッドを委譲するのに使えるのと同じく、型メソッドを型コンポーネントに委譲するのにdelegate typemethodを使うことが出来ます。

Snit 0.95 では、delegate methodはメソッドをインスタンスコンポーネント、型コンポーネントの両方に委譲することができたということにも注意してください。

Tkオプションデータベース

このセクションでは、どのようにSnitがTkオプションデータベースと相互作用し、オプションデータベースの情報を読み取ったり利用するかということについて説明します。Effective Tcl/Tk Programmingと同じく、Welch et alによる Practical Programming in Tcl and Tkがオプションデータベースのよい手引きです。

Snitは、ウィジェットの開発者がSnitで適切に振舞えば、大抵の場合はオプションデータベースに関してうまく動くように設計されています。このセクションの本文ではSnitが何を必用としているかについて詳しく扱います。次のリストは参考のために必用なことの概要です。

Tkウィジェットとオプションデータベースの相互作用は複雑です。Snitとオプションデータベースも複雑です。

ウィジェットクラスの設定:全てのTkウィジェットはウィジェットクラスを持っています。Tkウィジェットでは、ウィジェットクラスの名前はウィジェットの型名の一文字目を大文字にしたものです。例:buttonウィジェットのウィジェットクラスは"Button"です。

同じように、snit::widgetのデフォルトのウィジェットクラスは、最初の一文字が大文字の制限の無い型名になります。例えば次のウィジェットクラスの場合は

snit::widget ::mylibrary::scrolledText { ... }

"ScrolledText"になります。ウィジェットクラスはsnit::widget定義の中で明示的にwidgetclass文を使って設定することができます。

ウィジェットが-classオプションをサポートしていれば、そのウィじぇとクラス名を変更するhulltypeを使うことができます。先述したhulltypeコマンドの説明を見てください。ユーザーは-classオプションをウィジェットに渡すことも出来ます。

snit::widgetadaptorのウィジェットクラスはだたのhullウィジェットのウィジェットクラスです。

hullウィジェットが-classをサポートしている場合を除いては、 これを変更することはできないので、そのような場合は大体snit::widgetのほうがsnit::widgetadaptorよりも良いです。

オプションのリソース名とクラス名の設定:Tkでは、全てのオプションは三つの名前を持っています(オプション名、リソース名、クラス名)。オプション名はハイフンではじまり全て小文字です。それはウィジェットの作成時、configurecgetコマンドで使われます。

リソース名とクラス名は、Tkオプションデータベースに問い合わせてオプションをデフォルト値に初期化するのに使われます。リソース名は大抵はオプション名からハイフンを取り除き、単語の区切りごとに大文字にしたものです。クラス名は大抵はリソース名の最初の文字を大文字にしたものですが、必ずしもそうであるとは限りません。例えば、これはtextウィジェットのいくつかのオプション名、リソース名、クラス名です。

-background         background         Background 
-borderwidth        borderWidth        BorderWidth 
-insertborderwidth  insertBorderWidth  BorderWidth 
-padx               padX               Pad 

ちょっと見ると、リソースとクラスの名前はオプションの名前から推測できることがわかりますが、ただし、常にそうであるとはかぎりません。

Snitのオプションも、リソースとクラスの名前を持っています。デフォルトでは、これらの名前は先述のルールに従います。リソース名はオプション名からハイフンを除き、クラス名はリソース名の一文字目を大文字にしたものです。これはローカル定義されたオプションと明示的に委譲されたオプションに当てはまります。

snit::widget mywidget {
    option -background
    delegate option -borderwidth to hull
    delegate option * to text
# ...
}

この場合、ウィジェットのクラス名は"Mywidget"です。そしてウィジェットは次のオプションを持っています。-background(ローカル定義)、-borderwidth(明示的に委譲された)、その他のオプションはおそらくTkのtextウィジェットである"text"というコンポーネントに委譲されています。もしそうなら、mywidgettextウィジェットと全て同じオプションを持っています。オプション、リソース、クラスの名前は次のとおりです。

-background  background  Background
-borderwidth borderwidth Borderwidth
-padx        padX        Pad

ローカル定義されたオプションである-backgroundが標準のTkの-backgroundオプションと同じ三つの名前を持っているところに注目してください。そして、暗黙的にtextコンポーネントから委譲された-padの三つの名前が、textウィジェットと同じになっているところにも注目してください。 その一方で、-borderwidthは標準とは異なるリソースとクラスの名前を持っています。中の文字の"width"の一文字目が大文字になっていません。整合性をとるために、これは次のようにするべきです。

snit::widget mywidget {
    option -background
    delegate option {-borderwidth borderWidth} to hull
    delegate option * to text
    # ...
}

クラス名は期待したとおりに"BorderWidth"になります。

また、mywidget-padx-padyをhullに委譲していると仮定してみてください。この場合、リソース名とクラス名の両方とも明示的に設定されなければなりません。

snit::widget mywidget {
    option -background
    delegate option {-borderwidth borderWidth} to hull
    delegate option {-padx padX Pad} to hull
    delegate option {-pady padY Pad} to hull
    delegate option * to text
    # ...
}

オプションデータベースへの問い合わせ:widgetclassとオプション名を上記のように設定したら、インスタンスが作成されるごとに Snitはオプションデータベースに問い合わせをし、 大抵は オプションデータベースへの問い合わせは、適切に行うでしょう。 このセクションの残りはその泥臭い詳細について述べます。

ローカル定義されたオプションの初期化:snit::widgetのインスタンスが作成された時、そのローカル定義されたオプションは次のようにして初期化されます。各オプションのリソースとクラスの名前がTkオプションデータベースに問い合わせるために使われます。もし、そのリソースが空でなければ、その値がオプションのデフォルトとして使われますが、そうでなければ、型定義でハードコーディングされたデフォルト値が使われます。どちらの場合でも、デフォルトの値は呼び出し側で上書きすることができます。例えば次のとおりです。

option add *Mywidget.texture pebbled

snit::widget mywidget {
    option -texture smooth
    # ...
}

mywidget .mywidget -texture greasy

ここ、-textureは普通に"smooth"に設定されます。しかし、 オプションデータベースにそのオプションが登録されているので、そのデフォルトは"pebbled"に設定されます。しかしながら、呼び出し側で明示的にデフォルト値を上書きしているので、新しいウィジェットでは"greasy"になるでしょう。

hullに委譲されたオプションの初期化:snit::widgetのhullはウィジェットで、そのクラスはそれ自身のオプションデータベースに問い合わせて設定されます。唯一の例外は、異なる名前で委譲されたオプションに関係しています。次のコードを考えてみてください。

option add *Mywidget.borderWidth 5
option add *Mywidget.relief sunken
option add *Mywidget.hullbackground red
option add *Mywidget.background green

snit::widget mywidget {
    delegate option -borderwidth to hull
    delegate option -hullbackground to hull as -background
    delegate option * to hull
    # ...
}

mywidget .mywidget

set A [.mywidget cget -relief]
set B [.mywidget cget -hullbackground]
set C [.mywidget cget -background]
set D [.mywidget cget -borderwidth]

それでは質問です。A, B, C, Dの変数の値は何でしょうか。

Aの値は"sunken"です。hullはウィジェットクラスが"Mywidget"の Tkフレームです。自動的にオプションデータベースに問い合わせて、この値を取り出します。-reliefオプションは暗黙的にhullに委譲されたので、Snitは何もしていません。

Bの値は"red"です。hullは-reliefで値を取り出したように、自動的にその-backgroundオプションの"green"を取り出します。しかしながら、Snitは-hullbackgroundがhullの-backgroundオプションにマップされていることを知っているので、オプションデータベースに-hullbackgroundを問い合わせ、"red"を取得し、それに合わせてhullをアップデートします。

Cの値も"red"です。-backgroundは暗黙的にhullに委譲されているので、-hullbackgroundの取得と同じになります。この場合は普通の委譲ではない点に注意してください。普通は-backgroundはおそらく明示的に他のコンポーネントに委譲されているでしょう。

(訳注:BとCの説明は逆のような気がする)

Dの値は"5"です。考えるまでも無いことだと思うかもしれませんが、 上記のルールでは、-borderwidthのリソース名は"borderwidth"に設定されます、しかしながら、オプションデータベースへ"borderWidth"として登録しているところに注目してください。-relief同様に、Snitが何かする前に、hullはその-borderwidthオプションの値を取得します。 そのオプションは、自身の名前で委譲されているので、Snitは正しいことが行われていると推測し、これ以上何もおこないません。

snit::widgetadaptorでは、このようなケースは少し異なります。ウィジェットアダプタはhullのウィジェットクラスを保持し、Snitによってhullは自動的に作成されません。その代わり、snit::widgetadaptorinstallhullをコンストラクタで呼び出さなければなりません。普通の方法では次のようになります。

snit::widgetadaptor mywidget {
    # ...
    constructor {args} {
        # ...
        installhull using text -foreground white
        #
    }
    #...
}

この場合では、installhullコマンドは次のようなコマンドでhullを作成します。

set hull [text $win -foreground white]

hullはtextウィジェットで、そのウィジェットクラスは"Text"になります。snit::widgetのhullと同じように、Snitは自動的にその普通のオプションの値を全て取得します。異なる名前で委譲されたオプションは同じようにしてオプションデータベースから初期化されます。

他のコンポーネントに委譲されたオプションの初期化:hullでないコンポーネントは二つの方法でオプションデータベースに対して適合されます。一つ目は、コンポーネントウィジェットはまだウィジェットなので、一般的な方法でオプションデータベースから初期化されます。二つ目は、installコマンドを使ってコンポーネントに委譲された全てのオプションをオプションデータベースに問い合わせ、コンポーネントはそれに応じて初期化されます。

オプションデータベースのサポートがSnitに追加される以前は、単純にコンストラクタでコンポーネントを作成し、そのコマンド名をコンポーネントの変数に格納するという、一般的な方法で作成していました。

snit::widget mywidget {
    delegate option -background to myComp

    constructor {args} {
        set myComp [text $win.text -foreground black]
    }
}

この方法の欠点は、Snitがコンポーネントを適切に初期化する機会を持っていないことです。それゆえ、次のようなアプローチが今は使われています。

snit::widget mywidget {
    delegate option -background to myComp

    constructor {args} {
        install myComp using text $win.text -foreground black
    }
}

installコマンドは次のようなことをします。


非ウィジェットコンポーネント:オプションデータベースはsnit::typeのために絶対に問い合わせされません。なぜなら、それは既知のTkウィジェット名を問い合わせられるだけだからです。しかし、snit::widgetは非ウィジェットコンポーネントを持つことが出来ます。そして、もしオプションがこれらのコンポーネントに委譲されていて、これらのコンポーネントをインストールするのにinstallコマンドが使われていたら、それらのオプションは、ウィジェットコンポーネントのようにオプションデータベースから初期化されます。

マクロとメタプログラミング

snit::macroコマンドはSnitクラスでのメタプログラミングをある程度可能にします。例えば、set/getメソッドを持ったインスタンス変数である、プロパティを定義したいとします。あなたのコードはこのようになるでしょう。

snit::type dog {
    variable mood happy

    method getmood {} {
        return $mood
    }

    method setmood {newmood} {
        set mood $newmood
    }
}

プロパティごとに9行使っています。snit::macroを使って次のように定義することも出来ます。

snit::macro property {name initValue} {
    variable $name $initValue

    method get$name {} "return $name"

    method set$name {value} "set $name \$value"
}

snit::macroは、型とウィジェットの定義をコンパイルするスレーブインタープリタにある、ただのTclプロシージャだということに注目してください。結果として、型とウィジェットを定義するために使われる全てのコマンドにアクセスできます。

この新しいマクロによって、一行でプロパティを定義することが出来ます。

snit::type dog {
    property mood happy
}

マクロの中では、variableprocコマンドはTclの標準プロシージャではなく、Snitの型定義コマンドを参照しています。標準のTclコマンドを取得するには、_variable_procを使用してください。

アプリケーション中の全てのSnitの型とウィジェットをコンパイルのに使われているスレーブインタプリタは一つだけなので、マクロ名が衝突する可能性があります。 Snitを使って再使用可能なパッケージを書いていて、snit::macroを使っているなら、それらをあなたのパッケージの名前空間で定義してください。

snit::macro mypkg::property {name initValue} { ... }

snit::type dog {
    mypkg::property mood happy
}

これはアプリケーションの作者にとってグローバル名前空間を開けた状態にしておきます。

検証型

検証型とは、特定のTclの値を検証するのに使うことができるオブジェクトです。例えば、snit::integerはTclの値が整数かどうか検証するのに使われます。

全ての検証型は検証を行うvalidateメソッドを持っています。このメソッドは検証される値を引数に一つだけ取ります。さらに、もし値が適正であれば何もしませんが、値が不正な場合はエラーを投げます。

snit::integer validate 5     ;# Does nothing
snit::integer validate 5.0   ;# Throws an error (not an integer!)

Snitは検証型の様々な種類を定義しています。それらの全てはsnit::typeとして実装されています。それらはそのまま使うことが出来ます。加えて、それらのインスタンスはパラメータ化された亜種(サブタイプ)として役に立ちます。例えば、確率は0.0から1.0の間の数値です。

snit::double probability -min 0.0 -max 1.0

このサンプルはprobabilityというsnit::doubleのインスタンスを作成します。これは確率の値を検証するのに使うことが出来ます。

probability validate 0.5   ;# Does nothing
probability validate 7.9   ;# Throws an error

検証サブタイプは上記の例のように明示的に定義することができます。ローカル定義されたオプションで-typeが設定されると、それらはまたオンザフライに作成されます。

snit::enum ::dog::breed -values {mutt retriever sheepdog}

snit::type dog {
    # Define subtypes on the fly...
    option -breed -type {
        snit::enum -values {mutt retriever sheepdog}
    }

    # Or use predefined subtypes...
    option -breed -type ::dog::breed 
}

先述した動作をするvalidateメソッドを持つオブジェクトは検証型として使うことが出来ます。新しい検証型を定義する方法は 検証型の定義を見てください。

Snitは次の検証型を定義しています。

検証型の定義

新しい検証型を定義する方法は3つあります。一つ目はSnitの検証型のサブタイプ、二つ目は検証型コマンド、三つ目はSnitによって提供されている検証型に似た本格的な検証型です。Snitの検証型のサブタイプの定義は先述の検証型で説明しました。

その次に簡単な方法は、検証型コマンドとして新しい検証型を作成することです。検証型はvalidateメソッドを持ったシンプルなオブジェクトです。validateメソッドは値を引数に一つだけ取り、もし値が不正ならエラーを投げます。これは簡単なprocで行うことができます。例えば、snit::boolean検証型はこのように実装することができます。

proc ::snit::boolean {"validate" value} {
    if {![string is boolean -strict $value]} {
        return -code error  "invalid boolean \"$value\", should be one of: 1, 0, ..."
    }

    return
}

このようにして定義された検証型は当然ながらサブタイプ化できません。しかし、多くのアプリケーションにとってはこれで十分です。

最後に、本格的なサブタイプ化できる検証型をsnit::typeのように定義することができます。これはあなたが書くためのスケルトンです。

snit::type myinteger {
     # First, define any options you'd like to use to define
     # subtypes.  Give them defaults such that they won't take
     # effect if they aren't used, and marked them "read-only".
     # After all, you shouldn't be changing their values after
     # a subtype is defined.
     #
     # For example:

     option -min -default "" -readonly 1
     option -max -default "" -readonly 1

     # Next, define a "validate" type method which should do the
     # validation in the basic case.  This will allow the
     # type command to be used as a validation type.  

     typemethod validate {value} {
         if {![string is integer -strict $value]} {
             return -code error  "invalid value \"$value\", expected integer"
         }

         return
     }

     # Next, the constructor should validate the subtype options,
     # if any.  Since they are all readonly, we don't need to worry
     # about validating the options on change.

     constructor {args} {
         # FIRST, get the options
         $self configurelist $args

         # NEXT, validate them.

         # I'll leave this to your imagination.
     }

     # Next, define a "validate" instance method; its job is to
     # validate values for subtypes.

     method validate {value} {
         # First, call the type method to do the basic validation.
         $type validate $value

         # Now we know it's a valid integer.

         if {("" != $options(-min) && $value < $options(-min))  ||
             ("" != $options(-max) && $value > $options(-max))} {
             # It's out of range; format a detailed message about
             # the error, and throw it.

             set msg "...."
             
             return -code error $msg
         }

         # Otherwise, if it's valid just return.
         return
     }
}

で、このようにしてサブタイプ化できる型を作成できます。

Snitの配布物の中にある"validate.tcl"というファイルは全てのSnitの検証型を定義しています。snit::integerとその他の型の完全な実装をそこで見ることができます。自分で検証型を作成するときに参考にすることができます。

注意書き

もしバグを見つけたり、問題があったり、新しいアイデアなどを思いついたら、SourceForgeのtcllibのトラッカーにそれらを投稿してくれると本当にありがたいです。
http://sourceforge.net/projects/tcllib/
関連するカテゴリーはsnitです。

加えて、Snitのメーリングリストに入りたいと思うかもしれません。詳細は次のページを見てください。
http://www.wjduquette.com/snit

注意しなければならない分野は、他のメガウィジェットパッケージで作られたメガウィジェットを改造した snit::widgetadaptorの使用です。適切なウィジェットの破棄は<Destroy>のバインディングの順序に依存しています。賢明な選択肢は単純にこれをしないことです。

既知のバグ

ヒストリー

私の個人的なTclベースのノートブックアプリケーションである Notebook ( http://www.wjduquette.com/notebook を見てください) を開発している間に、私はオブジェクトの集合を書いているのに気がつきました。私は何か特定のオブジェクト指向のフレームワークを使っていませんでした。 私はただ、自分のオブジェクトコマンドのガイドライン (http://www.wjduquette.com/tcl/objects.html を見てください) に従い、いくつかちょっとしたトリックを加えながら、オブジェクトをピュアTclで書いていました。そして、それはうまく動きました。それからすぐに、新しいオブジェクト型ごとに必用な定型コードの量にうんざりするようになりました。

それが一つの理由でした。――退屈は強力なモチベーションです。しかし、その他の理由は、私が全く継承を使っていなくて、それで何も困っていないということに気がついたことです。その代わりに、私は委譲を使っていました。オブジェクトが他のオブジェクトを作り、メソッドをそれらに委譲していました。

そして私は独り言を言いました。「これはだんだんうんざりしてきた……。もっといい方法があるに違いない」。そして、ある日の午後、気まぐれに、Tclのように動くオブジェクトシステムSnitに取り組みはじめました。Snitは継承をサポートしていませんが、委譲は優れています。また、メガウィジェットも簡単に作成できます。

もし何かコメントや提案(またはバグ報告!)があったら気軽にe-mailを私に送ってください。さらに、Snitのめーリングリストがあります。Snitのホームページ( http://www.wjduquette.com/snit )で多くの情報を得ることができます。

クレジット

Snitはごく初期にはWilliam H. Duquetteによって設計と実装されていました。しかし、多くの功績ははSnitを使って貴重なフィードバックを提供してくれた次の人々のものです。Rolf Ade, Colin McCormack, Jose Nazario, Jeff Godfrey, Maurice Diamanti, Egon Pasztor, David S. Cargo, Tom Krehbiel, Michael Cleverly, Andreas Kupries, Marty Backe, Andy Goth, Jeff Hobbs, Brian Griffin, Donal Fellows, Miguel Sofer, Kenneth Green, and Anton Kovalenko. もし誰か忘れていたらごめんなさい。知らせてくれたらお名前をリストに追加するつもりです。

バグ、アイデア、フィードバック

このドキュメントと説明しているパッケージには 間違いなくバグや他の問題があるでしょう。それらを次のURLのsnitカテゴリに報告してください。
http://sourceforge.net/tracker/?group_id=12883
またパッケージと、ドキュメントに関して改善案があれば送ってください。


CategoryTclTk


|New|Edit|Freeze|Diff|History|Attach|Copy|Rename|
Last-modified: 2007-08-13 (Mon) 12:06:30
HTML convert time: 0.110 sec.