snit2.2/1.3のマニュアルを勝手に日本語に翻訳したものです。ほとんど直訳~
オリジナルの文書はhttp://tcllib.sourceforge.net/doc/snit.htmlです。
----
#contents
----
*名前 [#m2e48e36]
''snit -''~
Snit's Not Incr Tcl


*コマンド概略 [#id9df4c6]
 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


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


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


*リファレンス [#x425713d]
**型とウィジェットの定義 [#d8e27af4]
Snitは新しい型を定義するための次のコマンドを提供します。

-''snit::type'' '''name definition'''~
'''name'''という名前の新しい抽象データ型を定義します。
もし'''name'''が完全修飾コマンド名(名前空間を含んだ名前)でなければ、''snit::type''コマンドが呼び出された名前空間(大抵はグローバル名前空間)にあると仮定されます。このコマンドは新しい型の完全修飾された名前を返します。~
その型の名前は、従って、その新しい型のオブジェクトを作成したりなどをするのに使われるコマンドです。~
''snit::type''の'''definition'''ブロックは次の定義を含むスクリプトです。

--''typevariable'' '''name''' ?-array ? ? '''value''' ?~
設定された名前'''name'''で型変数を定義。オプションで'''value'''があれば、その値を割り当てます。
型変数はこの型の全てのインスタンスで共有されます。もし -arrayオプションがあれば、'''value'''は辞書でなければなりません。''array set''を使って変数に割り当てられます。

--''typemethod'' '''name arglist body'''~
新しい型コマンドのサブコマンドである型メソッドを指定された名前、引数リスト、ボディで定義。'''arglist'''は普通のTclの引数リストです。デフォルト引数と、''args''引数を含めることができますが、引数の名前として、''type''、''self''、''selfns''、''win''を使うことはできません。~
''type''変数は、''body''中で型の完全修飾名を値を持つ変数として自動的に定義されます。加えて、''type''変数は、自動的に全ての型メソッドの''body''中で可視化されます。~
もし'''name'''が二つ以上のトークンを含んでいる時は、Snitはそれを特別に処理します。~
 typemethod {a b} {arg} { puts "Got $arg" }
この文は暗黙的にbというサブコマンドを持っている、aという名前の型メソッドを定義します。 bはこのように呼び出されます。~
 $type a b "Hello, world!"
aは色々なサブコマンドを持っているかもしれません。これは階層的なコマンド構造を定義するのを可能にします。これらの多くの例は後述する''method''を見てください。~
型メソッドは、型が定義された名前空間からコマンドをインポートすること無しに呼び出すことができます。たとえば、もし、型の名前が ''::parentns::typename''なら、型の型メソッドは、 ''::parentns::someproc''を単に''someproc''として呼び出すことができます。'''Snit 1.x 非互換''':これはSnit1.xでは動きません。なぜなら、これはTcl8.5の新しいコマンドである''namespace path''に依存しているからです。~
'''Snit 1.x 非互換''':Snit 1.xでは次の二つの型メソッドの呼び出しは同じです。
 $type a b "Hello, world!"
 $type {a b} "Hello, world!"
Snit2.2では二つ目の呼び出しは不正です。

--''typeconstructor '' '''body'''~
型コンストラクタの'''body'''はその型が最初に定義された時に一度だけ実行されます。一般的にはarray変数型の型変数の初期化をしたり、[[Tkオプションデータベース>#tkoptiondatabase]]のエントリを追加したりといったことに使われます。~
''type''変数は、''body''中で型の完全修飾名を値を持つ変数として自動的に定義されます。加えて、''type''変数は、自動的に全ての型メソッドの''body''中で可視化されます。~
型は型コンストラクタを一つだけ定義できます。~
型コンストラクタは、型が定義された名前空間からコマンドをインポートすること無しに呼び出すことができます。たとえば、もし、型の名前が ''::parentns::typename''なら、型コンストラクタは、 ''::parentns::someproc''を単に''someproc''として呼び出すことができます。'''Snit 1.x 非互換''':これはSnit1.xでは動きません。なぜなら、これはTcl8.5の新しいコマンドである''namespace path''に依存しているからです。~

--''variable'' '''name''' ? -array ? ? '''value''' ?~
インスタンス変数を定義します。この型の各インスタンスのプライベート変数です。オプションで初期値を持ちます。もし -arrayオプションがあれば、'''value'''は辞書でなければなりません。''array set''を使って変数に割り当てられます。

--''method'' '''name arglist body'''~
インスタンスメソッドを定義。指定された名前、引数リスト、ボディを持つ、この型の各インスタンスのサブコマンドです。'''arglist'''は普通のTclの引数リストです。デフォルト引数と、''args''引数を含めることができます。メソッドは暗黙的に次の引数を追加で渡します。''type'':型の完全修飾名、''self'':現在のインスタンスのコマンド名、''selfns'':寸スタンスのプライベート名前空間、''win'':オリジナルのインスタンス名。そういうわけで、'''arglist'''は引数名として、''type'', ''self'', ''selfns'', ''win''を含んではいけません。~
このように定義されたインスタンスメソッドは''ローカル定義''されたメソッドといいます。~
型とインスタンス変数は自動的に全てのインスタンスメソッド中で可視化されます。もしその型がローカル定義されたオプション(後述)を持っていたら、その''options''配列も可視です。
もし'''name'''が二つ以上のトークンを含んでいる時は、Snitはそれを特別に処理します。~
 method {a b} {} { ... }
この文は暗黙的にbというサブコマンドを持っている、aという名前の型メソッドを定義します。 bはこのように呼び出されます。~
 $self a b "Hello, world!"
aは色々なサブコマンドを持っているかもしれません。これは階層的なコマンド構造を定義するのを可能にします。
 % snit::type dog {
     method {tail wag}   {} {return "Wag, wag"}
     method {tail droop} {} {return "Droop, droop"}
 }
 ::dog
 % dog spot
 ::spot
 % spot tail wag
 Wag, wag
 % spot tail droop
 Droop, droop
 %
私たちがしたことは、"wag"と"droop"サブコマンドを持っている"tail"メソッドの暗黙的な定義です。ですから、"tail"を明示的に定義すればエラーになります。~
メソッドは、型が定義された名前空間からコマンドをインポートすること無しに呼び出すことができます。たとえば、もし、型の名前が ''::parentns::typename''なら、型の型メソッドは、 ''::parentns::someproc''を単に''someproc''として呼び出すことができます。'''Snit 1.x 非互換''':これはSnit1.xでは動きません。なぜなら、これはTcl8.5の新しいコマンドである''namespace path''に依存しているからです。~
'''Snit 1.x 非互換''':Snit 1.xでは次の二つの型メソッドの呼び出しは同じです。
 $self a b "Hello, world!"
 $self {a b} "Hello, world!"
Snit2.2では二つ目の呼び出しは不正です。

--''option'' '''namespec ? defaultValue ?'''
--''option'' '''namespec ? options... ?'''~
この型の各インスタンスのオプションを定義する。初期値が与あればそれを代入する。この初期値に用いられるデフォルトの値は空文字列ですが、'''defaultValue'''で変更することができます。~
このように定義されたオプションはローカル定義されたものと呼ばれます。~
'''namespec'''はオプションの名前、リソース名、クラス名を定義したリストです。例:
 option {-font font Font} {Courier 12}
オプション名はハイフン(-)で始まらなければなりません。そして、大文字を含んではいけません。リソース名とクラス名は記述しないで省略することができます。リソース名はデフォルトではオプション名の先頭からハイフンを除いたもので、クラス名はデフォルトではリソース名の最初の一文字を大文字にしたものになります。したがって、次の文は、先ほどの例と同じになります。
 option -font {Courier 12}
リソースとクラス名についての詳細は[[Tkオプションデータベース>#tkoptiondatabase]]を見てください。~
オプションは普通セットしたり取り出したりするのに、一般的なインスタンスメソッドの''configure''と''cget''を使います。インスタンスのコードの中(メソッドのボディなど)からは、オプションの値は''options''配列から使うことができます。
 set myfont $options(-font)
もし型がオプションハンドラ(例:-configuremethod)を定義していたら、ややこしいバグを避けるために、そのオプションにアクセスするときは''configure''と''cget''を使うべきでしょう。''option''の文は次のオプションを含むことができます。

--- -default '''defvalue'''~
オプションのデフォルト値を定義します。省略された場合、オプションのデフォルト値は空文字列""になります。

--- -readonly '''flag'''~
'''flag'''はTclが認識できる真偽値です(true/false, yes/no, 1, 0)。オプションがread-onlyのときは、''configure''か''configurelist''を使って生成時のみに値を代入することができます。例:型のコンストラクタ。

--- -type '''type'''~
全てのローカル定義されたオプションはそのデータ検証の型を定義することができます。それは検証型の名前か亜型(サブタイプ)のどちらかです。~
例えば、あるオプションは、''snit::integer''を検証型として設定することで、その値が整数であると宣言できます。
 option -number -type snit::integer
また、サブタイプを設定して、その値を1から10の間の整数として宣言できます。
 option -number -type {snit::integer -min 1 -max 10}
もし、検証型かサブタイプのどちらかがオプションに定義されれば、オブジェクトの''configure''か''configurelist''メソッドからオプションの値が変更されたときに、検証されます。さらに、そのようなオプションは全て、コンストラクタが実行された後、自動的に暗黙的に検証されます。~
Snitは様々な種類の検証型とサブタイプを定義していますし、
新しい検証型を定義するのも本当に簡単です。全ての検証型のリストは[[検証型>#validationtypes]]を見てください。自分で定義する方法の説明は、[[検証型の定義>#definevalidationtypes]]を見てください。

--- -cgetmethod '''methodName''' ~
ローカル定義された全てのオプションは-cgetmethodを定義することができます。これはオプションの値が''cget''メソッドを使って読み出されるときに呼び出されます。メソッドの'''body'''が返す値が'''cget'''呼び出しの返り値として返ります。~
この指定されるメソッドが取る引数は一つでなければなりません。例えば、このコードはSnitのデフォルトの''cget''の振る舞いと(速度は遅いですが)同じです。
 option -font -cgetmethod GetOption
 method GetOption {option} {
     return $options($option)
 }
いくつのオプションが-cgetmethodを共有してもよいことに注意してください。

--- -configuremethod '''methodName'''~
ローカル定義された全てのオプションは-configuremethodを定義することができます。これはオプションの値が''configure''または''configurelist''メソッドから代入されたときに呼び出されます。オプションの値を保存するのは、指定されたメソッドの責任です。言い換えると、そのメソッドが値を保存しない限り、値は''options()''配列には保存されません。~
指定されたメソッドは、オプション名とその新しい値の引数を二つ取らなければなりません。例えば、このコードはSnitのデフォルトの''configure''の振る舞いと、(速度は遅いですが)同じです。
 option -font -configuremethod SetOption
 method SetOption {option value} {
     set options($option) $value
 }
複数のオプションが一つの-configuremethodを共有できることに注意してください。

--- -validatemethod '''methodName'''~
ローカル定義された全てのオプションは-validatemethodを定義することができます。これは、ちょうどさきほどの-configuremethodのように、オプションの値が''configure''または''configurelist''メソッドから代入されたときに呼び出されます。オプションの新しい値を検証し。もし不正な値ならエラーを投げるのが、指定されたメソッドの責任です。~
指定されたメソッドは、オプション名とその新しい値の引数を二つ取らなければなりません。例えば、このコードは-flagの値が正しい真偽値かどうか検証します。
 option -flag -validatemethod CheckBoolean
 method CheckBoolean {option value} {
     if {![string is boolean -strict $value]} {
         error "option $option must have a boolean value."
     }
 }
複数のオプションが一つの-validatemethodを共有できることに注意してください。

--''constructor'' '''arglist body'''~
コンストラクタ定義は、新しいインスタンスが生成されたときに実行されるコードの'''body'''を設定します。'''arglist'''は普通のTclの引数リストで、デフォルト引数と''args''引数を含んでいても構いません。~
メソッドと同様に、''type''、''self''、''selfns''、''win''の引数が暗黙的に定義されます。そして、全ての型変数とインスタンス変数は自動的にコンストラクタの'''body'''で可視化されます。~
もしコンストラクタが明示的に定義されなかったら、Snitはそれを暗黙的に定義します。もし型が少なくとも一つのオプションを(ローカルか委譲によって)定義していたら、デフォルトのコンストラクタは次のように定義されるでしょう。~
 constructor {args} {
     $self configurelist $args
 }
標準的なTkウィジェットのような振る舞いのためには、このように引数リストは''args''一つだけにするべきです。~
もし、コンストラクタとオプションのどちらも定義されていなければ、デフォルトのコンストラクタはこのようになります。~
 constructor {} {}
メソッドと同様に、コンストラクタは、型が定義された名前空間からコマンドをインポートすること無しに呼び出すことができます。たとえば、もし、型の名前が ''::parentns::typename''なら、コンストラクタは、 ''::parentns::someproc''を単に''someproc''として呼び出すことができます。'''Snit 1.x 非互換''':これはSnit1.xでは動きません。なぜなら、これはTcl8.5の新しいコマンドである''namespace path''に依存しているからです。~

--''destructor'' '''body'''~
デストラクタは型のインスタンスが破棄されるときに実行しなければならないコードを定義します。一般的には、コンストラクタで生成した物の破棄に使われます。~
デストラクタは明示的に引数を取りません。
メソッドと同様に、''type''、''self''、''selfns''、''win''の引数が暗黙的に定義されます。そして、全ての型変数とインスタンス変数は自動的にデストラクタの'''body'''で可視化されます。~
メソッドと同様に、デストラクタは、型が定義された名前空間からコマンドをインポートすること無しに呼び出すことができます。たとえば、もし、型の名前が ''::parentns::typename''なら、 ''::parentns::someproc''を単に''someproc''として呼び出すことができます。'''Snit 1.x 非互換''':これはSnit1.xでは動きません。なぜなら、これはTcl8.5の新しいコマンドである''namespace path''に依存しているからです。~

--''proc'' '''name args body'''~
型の名前空間に新しくTclプロシージャを定義します。~
定義されたプロシージャは、普通のTclプロシージャと全ての型変数は自動的に可視になる点で異なります。さらに、このプロシージャは引数の一つである''selfns''を通じてインスタンス変数にもアクセスできます。~
暗黙的に定義されていないとしても、type、self、winという引数の名前は避けるべきです。~
メソッドと型メソッドと同様に、プロシージャは、型が定義された名前空間からコマンドをインポートすること無しに呼び出すことができます。たとえば、もし、型の名前が ''::parentns::typename''なら、 ''::parentns::someproc''を単に''someproc''として呼び出すことができます。'''Snit 1.x 非互換''':これはSnit1.xでは動きません。なぜなら、これはTcl8.5の新しいコマンドである''namespace path''に依存しているからです。~

--''delegate'' method '''name''' to '''comp''' ? as '''target'''~
'''name'''という名前のメソッドを'''comp'''という名前のコンポーネントに委譲します。つまり、'''name'''メソッドがこの型のインスタンスで呼び出されると、そのメソッドとその引数は、呼び出されたそのメソッドの代わりに、指定されたコンポーネントのコマンドに送られます。つまり、次の文は、
 delegate method wag to tail
大雑把に言えば、この明示的に定義されたメソッドと同じです。
 method wag {args} {
     uplevel $tail wag $args
 }
メソッドと同様に、'''name'''は複数のトークンを持つことができます。この場合、その名前の最後のトークンはコンポーネントの名前になります。~
オプションのas節は、委譲されたメソッドの名前を設定し、場合によっては追加の引数を付加することを可能にします。
 delegate method wagtail to tail as "wag briskly"
メソッドはローカル定義と委譲の両立はできません。~
重要:全ての''delegate method''の形式では、インスタンスコンポーネントと型コンポーネントの両方に委譲できます。

--''delegate'' method '''name''' ? to '''comp''' ? using '''pattern'''~
この形式での''delegate''文は、using節を使い、
適切なコマンドの形式が、どのメソッド'''name'''が委譲されるのかを指定します。この形式では、to節は省略可能です。なぜなら、選択されたコマンドはどのコンポーネントも実行しないだろうからです。~
using節の値は、次の置換えコードのいくつか、または全てを含むリストです。これらのコードは委譲されたコマンド接頭辞を構築するために、次に説明する値で置き換えられます。次の二つの文は同じだということに注意してください。
 delegate method wag to tail
 delegate method wag to tail using "%c %m"
リストの各要素は委譲コマンドの要素になります。
各要素は絶対に文字列として再解析されません。
--- %%~
"%"に置き換えます。文字列"%c"を引数としてコマンドに渡したいときは、"%%c"と書きます。
--- %c~
指定されたコンポーネントのコマンドに置き換えます。
--- %m~
メソッド'''name'''の最後のトークンに置き換えます。
もし'''name'''が一つのトークンだけの場合、%Mと同じになります。
--- %M~
メソッド'''name'''に置き換えます。もし'''name'''が複数のトークンで構成されている場合はスペースで連結されます。
--- %j~
メソッド'''name'''に置き換えます。もし'''name'''が複数のトークンで構成されている場合はアンダースコア("_")で連結されます。
--- %t~
型の完全修飾名に置き換えます。
--- %n~
インスタンスのプライベート名前空間に置換えます。
--- %s~
インスタンスコマンドに置き換えます。
--- %w~
インスタンスコマンドのオリジナル名に置き換えます。Snitウィジェットとウィジェットアダプターでは、これはTkウィンドウの名前です。たとえインスタンスコマンドがリネームされても、置換えの値は変わりません。

--''delegate'' method * ? to '''comp''' ? ? using '''pattern''' ? ? except '''exceptions''' ?~
''delegate method *''形式では、全ての未知のメソッド名を指定されたコンポーネント'''comp'''に委譲します。except節は例外(委譲されるべきではないメソッド名)のリストを指定するのに使うことができます。using節は先述したように定義することができます。この形式では、文はto節かusing節、またはその両方を必ず含んでいないといけません。~
実際のところ、"*"は二つ以上のトークンのリスト(ただし最後の要素は"*")にすることができます。
 delegate method {tail *} to tail
これは暗黙的に、メソッド''tail''を定義し、そのサブコマンドはコンポーネント''tail''に委譲されます。

--''delegate'' option '''namespec''' to '''comp'''
--''delegate'' option '''namespec''' to '''comp''' as '''target'''
--''delegate'' option * to '''comp'''
--''delegate'' option * to '''comp''' except '''exceptions'''~
委譲されたオプションを定義します。'''namespec'''は''option''文のために定義されます。~
オプションの値を変更したり読み取ったりするために''configure''、''configurelist''、または''cget''インスタンスメソッドが使われると、''configure''、''cget''コマンドに相当するものが、まるで、オプションが次の-configuremethodと-cgetmethodで定義されているかのように、コンポーネントに適用されます。
 method ConfigureMethod {option value} {
     $comp configure $option $value
 }
 
 method CgetMethod {option} {
     return [$comp cget $option]
 }
委譲されたオプションは''options''配列には存在しないことに注意してください。~
もしas節が設定されていると、'''target'''オプション名が'''name'''のかわりに使われます。~
''delegate option*''形式では、全ての未知のオプションを指定されたコンポーネント'''component'''に委譲します。except節は、例えば委譲されないオプションの名前の例外リスト'''exceptions'''を設定することができます。~
注意:オプションはインスタンスメソッドの ''configure''と''cget''をサポートしているコンポーネントにだけ委譲できます。
オプションはローカル定義と委譲の両立はできません。TBD: Continue from here.

--''component'' '''comp''' ? -public '''method''' ? ? -inherit '''flag''' ?~
コンポーネント'''comp'''を明示的に宣言し、自動的に
コンポーネントのインスタンス変数を定義します。~
もし-publicオプションが指定されると、サブコマンドがコンポーネントに委譲される'''method'''を定義することで、
そのオプションはパブリックになります。例えば-public mycompが設定されると、次のコードと同じになります。
 component mycomp
 delegate method {mymethod *} to mycomp
もし-inheritオプションが指定されると、'''flag'''は真偽値でなければなりません。もし'''flag'''が真なら、全ての未知のメソッドとオプションはこのコンポーネントに委譲されます。-inheritという名前はこの新しい型のインスタンスが、コンポーネントのメソッドとオプションを継承するという程度の意味です。つまり、-inherit yesは次の文と同じです。
 component mycomp
 delegate option * to mycomp
 delegate method * to mycomp

--''delegate'' typemethod '''name''' to '''comp''' ? as '''target''' ?~
'''name'''の型メソッドを型コンポーネント'''comp'''に委譲する。つまり、型メソッド'''name'''が呼び出されると、その型メソッドと引数は指定された型コンポーネントのコマンドに引き渡されます。つまり、次のような文では
 delegate typemethod lostdogs to pound
大雑把に言えば、明示的に定義された次のようなメソッドと大体同じです。
 typemethod lostdogs {args} {
     uplevel $pound lostdogs $args
 }
メソッドと同様に、'''name'''は複数のトークンを持つことができます。この場合、'''name'''の最後のトークンはそのコンポーネントのメソッドとして仮定されます。~
オプションのas節は、委譲されたメソッドの名前を設定し、場合によっては追加の引数を付加することを可能にします。
 delegate typemethod lostdogs to pound as "get lostdogs"
型メソッドはローカル定義と委譲の両立はできません。

--''delegate'' typemethod '''name''' ? to '''comp''' ? using '''pattern'''~
この形式での''delegate''文は、using節を使い、
適切なコマンドの形式が、どの型メソッド'''name'''が委譲されるのかを指定します。この形式では、to節は省略可能です。なぜなら、選択されたコマンドはどの型コンポーネントも実行しないだろうからです。~
using節の値は、次の置換えコードのいくつか、または全てを含むリストです。これらのコードは委譲されたコマンド接頭辞を構築するために、次に説明する値で置き換えられます。次の二つの文は同じだということに注意してください。
 delegate typemethod lostdogs to pound
 delegate typemethod lostdogs to pound using "%c %m"
リストの各要素は委譲コマンドの要素になります。
各要素は絶対に文字列として再解析されません。
--- %%~
"%"に置き換えます。文字列"%c"を引数としてコマンドに渡したいときは、"%%c"と書きます。
--- %c~
指定された型コンポーネントのコマンドに置き換えます。
--- %m~
型メソッド'''name'''の最後のトークンに置き換えます。
もし'''name'''が一つのトークンだけの場合、%Mと同じになります。
--- %M~
型メソッド'''name'''に置き換えます。もし'''name'''が複数のトークンで構成されている場合はスペースで連結されます。
--- %j~
型メソッド'''name'''に置き換えます。もし'''name'''が複数のトークンで構成されている場合はアンダースコア("_")で連結されます。
--- %t~
型の完全修飾名に置き換えます。

--''delegate'' typemethod * ? to '''comp''' ? ? using '''pattern''' ? ? except '''exceptions''' ?~
''delegate typemethod *''形式では、全ての未知の型メソッド名を指定された型コンポーネント'''comp'''に委譲します。except節は例外(委譲されるべきではない型メソッド名)のリストを指定するのに使うことができます。using節は先述したように定義することができます。この形式では、文はto節かusing節、またはその両方を必ず含んでいないといけません。~
注意:デフォルトでは、Snitは(fooが型メソッドとして定義されていない場合の)''$type foo"を、(fooがその型の新しいインスタンスの名前である場合の)''$type create foo''と等しいと解釈します。もし''delegate typemethod *''を使うなら、型メソッド''create''を必ず明示的に使用しなければなりません。~
"*"は二つ以上のトークンのリスト(ただし最後の要素は"*")にすることができます。
 delegate typemethod {tail *} to tail
これは暗黙的に、型メソッド''tail''を定義し、そのサブコマンドは型コンポーネント''tail''に委譲されます。

--''typecomponent'' '''comp''' ? -public '''typemethod''' ? ? -inherit '''flag''' ?~
型コンポーネント'''comp'''を明示的に宣言し、自動的にコンポーネントの型変数を定義します。型コンポーネントは、型メソッドとインスタンスメソッドが委譲可能な任意のコマンドです。そのコマンドの名前は型変数に格納されます。
もし-publicオプションが指定されると、型コンポーネントは
サブコマンドがコンポーネントに委譲される
'''typemethod'''を定義することでパブリックになります。
例えば、-public mytypemethod が設定されると、それは
次のコードと同じになります。
 typecomponent mycomp
 delegate typemethod {mytypemethod *} to mycomp
もし-inheritオプションが指定されると、'''flag'''は真偽値でなければなりません。もし'''flag'''が真なら、全ての未知の型メソッドはこの型コンポーネントに委譲されます。(上記の"delegate typemethod *"の記述を見てください。) -inheritという名前はこの型が、型コンポーネントの振る舞いを継承するという程度の意味です。つまり、-inherit yesは次の文と同じです。
 typecomponent mycomp
 delegate typemethod * to mycomp

--''pragma'' ? '''options...''' ?~
''pragma''文はSnitが型を生成する方法をコントロールします。次のオプションを取ります。どのオプションでも'''flag'''はTclが認識できる真偽値(0, 1, yes, no, true, false)でなければなりません。~
-hastypeinfoと-hastypedestroyと-hasinstancesをFALSEに設定し、適切な型メソッドを定義することで、 副作用無しにアンサンブルコマンドを作成することが出来ます。

--- -canreplace '''flag'''~
FALSE(デフォルト)なら、Snitは既存のコマンドと同じ名前を持つ''snit::type''のインスタンスを作成しません。これはややこしいエラーを防ぎます。このプラグマをTRUEに設定すれば、Snit V0.93以前のバージョンの動作と同じになります。

--- -hastypeinfo '''flag'''~
TRUE(デフォルト)なら、生成された型は、型の内省に使われる''info''という型メソッドを持ちます。型メソッド''info''については後述しています。もしFALSEなら持ちません。

--- -hastypedestroy '''flag'''~
TRUE(デフォルト)なら、生成された型は、その型と、その型の全てのインスタンスを破棄するのに使われる''destroy''という型メソッドを持ちます。型メソッド''destroy''については後述しています。もしFALSEなら持ちません。

--- -hastypemethods '''flag'''~
TRUE(デフォルト)なら、生成された型の型コマンドはサブコマンド(型メソッド)を持ちます。FALSEなら型コマンドはサブコマンドを持たず、最初の引数をインスタンスの名前としてインスタンスを生成する機能だけを提供します。~
このプラグマと-hasinstancesを両方同時にFALSEにすることはできません。

--- -hasinstances '''flag'''~
TRUE(デフォルト)なら、生成された型は、インスタンスに関連した様々な機能と、型のインスタンスを生成するのに使われる''create''という名前の型メソッドを持ちます。もしFALSEなら持ちません。~
このプラグマと-hastypemethodsを両方同時にFALSEにすることはできません。

--- -hasinfo '''flag'''~
TRUE(デフォルト)なら、生成された型のインスタンスは、インスタンスの内省に使われる''info''というインスタンスメソッドを持ちます。''info''メソッドは後述しています。FALSEなら持ちません。

--- -simpledispatch '''flag'''~
このプラグマは 頻繁に利用される抽象データ型(たとえばスタックとキュー)をより効率的にするために、簡単にすることを目的としています。FALSE(デフォルト)なら、インスタンスメソッドは普通にディスパッチされます。TRUEなら、より高速なディスパッチ機構が代わりに使われます。スピードの代償として、-simpledispatch yesにすると、次のような制限があります。
> ・メソッドは委譲できません。
> ・''uplevel''と''upvar''は期待したようには動きません。呼び出し側のスコープは1レベルでなく2レベル上です。
> ・オプションを操作するメソッド(''cget''、''configure''、''configurelist'')は本当にちょっとだけ遅いです。

--''expose'' '''comp'''
--''expose'' '''comp''' as '''method'''~
廃止予定。コンポーネント'''comp'''をパブリックにするには''component''の-publicオプションを使用してください。

--''onconfigure'' '''name arglist body'''~
廃止予定。''option''の-configuremethod を代わりに使用してください。~
バージョン0.95時点での次のような定義は
 option -myoption
 onconfigure -myoption {value} {
     # Code to save the option's value
 }
次のように実装されます。
 option -myoption -configuremethod _configure-myoption
 method _configure-myoption {_option value} {
     # Code to save the option's value
 }

--''oncget'' '''name body'''~
廃止予定。''option''の-cgetmethod を代わりに使用してください。~
バージョン0.95時点での次のような定義は
 option -myoption
 oncget -myoption {
     # Code to return the option's value
 }
次のように実装されます。
 option -myoption -cgetmethod _cget-myoption
 method _cget-myoption {_option} {
     # Code to return the option's value
 }

-''snit::widget'' '''name definition'''~
このコマンドは指定された'''name'''でSnitメガウィジェット型を定義します。'''definition'''は ''snit::type''と同じように定義されますが、''snit::widget''は''snit::type''と次の点で異なっています。

--全ての''snit::widget''のインスタンスは自動的に生成されたコンポーネント''hull''を持ちます。''hull''は普通のTkフレームウィジェットです。他のメガウィジェットの一部として生成されたウィジェットは、この''hull''の中に作成されます。~
hullコンポーネントは、最初は要求されたウィジェット名で作成され、それからSnitがちょっとゴニョゴニョして、そのhullコンポーネントをリネームし、自身のインスタンスコマンドを適切にインストールします。hullコンポーネントの新しい名前は''hull''という名前のインスタンス変数に保存されます。

--インスタンスの名前は正当なTkのウィンドウ名であり、かつ、親ウィンドウが存在していなければなりません。

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

--''widgetclass'' '''name'''~
''snit::widget''のウィジェットクラスをデフォルトの値を上書きして'''name'''に設定する。詳細は[[Tkオプションデータベース>#tkoptiondatabase]]を見てください。

--''hulltype'' '''type'''~
''snit::widget''のhullとして使われるウィジェットの種類を決定します。'''type'''はframe(デフォルト)、toplevel、labelframe、完全修飾名のtk::frame、tk::toplevel、tk::labelframeを設定できます。または、もし可能ならば、同等のTileウィジェットの、ttk::frame、ttk::toplevel、ttk::labelframeも設定できます。実際には、-classオプションをサポートしていれば、''snit::hulltypes''変数にその名前を''lappend''することで どのウィジェットでもhullウィジェットとして使うことが出来ます。

-''snit::widgetadaptor'' '''name definition'''~
このコマンドは指定された'''name'''でSnitメガウィジェット型を定義します。''snit::widget''との違いは、インスタンスの''hull''コンポーネントが自動的に作成されない点で、hullはコンストラクタで生成され、''installhull''コマンドを使ってインストールされます。一度hullがインストールされると、そのインスタンスコマンドはリネームされ、普通の''snit::widget''として置き換えられます。オリジナルのコマンドはインスタンス変数''hull''を通じて再びアクセス可能です。~
一般的に snit::widgetadaptor のhullウィジェットの '''widget class'''を変更するのは不可能ということに 注意してください。~
どうやって''snit::widgetadaptor''がオプションデータベースとやりとりしているのかという情報は、[[Tkオプションデータベース>#tkoptiondatabase]]を見てください。

-''snit::typemethod'' '''type name arglist body'''~
既存の'''type'''のための新しい型メソッドを定義する(または、既存の型メソッドを再定義する)。

-''snit::method'' '''type name arglist body'''~
既存の'''type'''のための新しいインスタンスメソッドを定義する(または既存のインスタンスメソッドを再定義する)。
委譲されたインスタンスメソッドは再定義できない点に注意してください。

-''snit::macro'' '''name arglist body'''~
指定された'''name arglist body'''でSnitマクロを定義します。マクロは 新しい型とウィジェット定義文を定義するのに使われます。~
マクロとは単純に、型とウィジェット定義をコンパイルするためのスレーブインタプリタで定義された、Tclプロシージャです。従って、マクロは全ての型とウィジェット定義文へアクセスできます。詳細は[[マクロとメタプログラミング>#macroandmetaprog]]を見てください。~
マクロ'''name'''は 他の標準のTclコマンドや他のSnitの型とウィジェット定義文と同じようにはできません。例えば、''method''または''delegate''文、または標準の''set''、''list''、''string''コマンドを再定義することはできません。

-''snit::compile'' '''which type body'''~
Snitは定義文をTclスクリプトに「コンパイル」することで型、ウィジェット、ウィジェットアダプタを定義します。このスクリプトは、実際に新しい型を定義するTclインタプリタで実行されます。~
このコマンドは「コンパイラ」をさらけ出します。指定された'''type'''(ここでは'''type'''、'''widget'''、'''widgetadaptor'''のどれか)の'''body'''定義が与えられると、''snit::compile''は二つの要素のリストを返します。最初の要素は完全修飾名で、二つ目の要素はスクリプト定義です。~
''snit::compile''は、Snitが生成したコードに追加処理が終われなければならないときに便利です。例えば、TclDevKitコンパイラに通すようなときなど便利です。加えて、返り値のスクリプトは".tcl"ファイルに保存して、アプリケーションやライブラリの一部として型を定義することができます。
このようにして、アプリケーションの起動時のコンパイルのオーバーヘッドを減らすことができます。コンパイル時と同じバージョンのSnitがランタイムとして使われていなければならない点に注意してください。


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

-''$type'' '''typemethod args...'''~
'''typemethod'''は [[標準的な型メソッド>#standardtypemethods]] のいずれか(例:''create'')、または型定義で定義された型メソッドのいずれかです。その次の'''args'''は選択された'''typemethod'''によって異なります。~
型コマンドはほとんどの場合、新しい型のインスタンスを作成するために使われます。それゆえ、もし型コマンドの最初の引数が妥当な型メソッドを指定していない場合、''create''メソッドだと推測され実行されます。 ただし型定義が''delegate typemethod *''を含んでいるか-hasinstancesプラグマがFALSEに設定されている場合は除きます。
さらに、もし -hastypemethods プラグマがFALSEの場合、Snitの型コマンドを引数なしで呼び出すことができます。この場合、型コマンドは自動的に生成した名前をつけたインスタンスを作成します。言い換えると、-hastypemethods プラグマがFALSEで型がインスタンスを作成できる場合、次のコマンドは全て同等です。
 snit::type dog { ... }
 
 set mydog [dog create %AUTO%]
 set mydog [dog %AUTO%]
 set mydog [dog]
これは明白な理由からSnitウィジェットでは動きません。~
'''Snit 1.x 非互換''':Snit 1.xでは上記の動作は-hastypemethodsをTRUE(デフォルト)かFALSEにすることで実現することができます。


**標準的な型メソッド &aname(standardtypemethods); [#ue850dae]
型定義での型メソッドに加えて、全ての型とウィジェットコマンドは普通少なくとも次のサブコマンドを持っています。

-''$type create''  '''name'''?  '''option value ...'''?~
指定された'''name'''をつけた型のインスタンスを新しく作成し、型のコンストラクタを呼び出します。で'''snit::type'''は、もし'''name'''が完全修飾名でなければ、それはsnit::typeが呼び出された名前空間中にあると推測されます。このメソッドは完全修飾名を返します。~
''snit::widget''と''snit::widgetadaptor''の場合、'''name'''は有効なウィジェット名でなければなりません。このメソッドはウィジェット名を返します。~
'''name'''が他の型メソッドの名前と衝突しない限りは、''create''キーワードは省略することができます。ただし、型定義が''delegate typemethod *''を含んでいるか、-hasinstancesがFALSEに設定されている場合はできません。~
もし'''name'''が%AUTO%という文字列を含んでいると、それは$type$counter という文字列に置き換えられます。ここで$typeは型名で$counterは%AUTO%がこの型で使われるたびに増える数値です。~
デフォルトでは、'''name'''に続く引数はオプションの名前と、その値のリストになります。しかしながら、型のコンストラクタは異なる引数リストを設定することができます。~
Snit V0.95以後は、もし'''name'''が既存のコマンド名と同じ場合、''create''はエラーを投げます。すでに''snit::widget''と''snit::widgetadaptor''ではこのような動作になっていたことに注意してください。-canreplace プラグマを使うことで既存の動作を置き換えることができます。

-''$type info typevars'' ?  '''pattern'''?~
型の型変数(Snitの内部変数を除く)のリストを返します。全ての変数の名前は完全修飾されます。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。

-''$type info typemethods'' ?  '''pattern'''?~
型の型メソッドのリストを返します。もし型が階層的な型メソッドを持っているなら(ローカル定義されていようが委譲されていようが) 最初のトークンだけがリストに含まれます。~
もし型定義が''delegate typemethod *''を含んでいる場合、そのリストは(少なくとも一回呼び出されて型メソッドキャッシュにある)暗黙的に委譲された型メソッドの名前のみ含むでしょう。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。

-''$type info args''  '''method'''~
型の'''method'''の引数の名前のリストを返します。
このメソッドは委譲された型メソッドには適用できません。

-''$type info body''  '''method'''~
型メソッド'''method'''のボディを返します。このメソッドは委譲された型メソッドには適用できません。

-''$type info default''  '''method aname varname'''~
'''method'''の引数の'''aname'''がデフォルト値を持っているかどうか真偽値を返します。持ってる場合はTRUE、持ってない場合はFALSE。もし引数がデフォルト値を持ってる場合、変数'''varname'''にその値が代入されます。

-''$type info instances'' ?  '''pattern'''?~
型のインスタンスのリストを返します。''snit::type''では、完全修飾された名前のリストです。''snit::widget''では、Tkウィジェットの名前のリストです。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。~
'''Snit 1.x 非互換''':Snit 1.xでは階層的な型メソッドの複数単語名は返り値に含まれます。

-''$type destroy ''~
型のインスタンス、型の名前空間、型コマンド自身を破棄します。


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

-''$object''  '''method args...'''~
'''method'''は [[標準的なインスタンスメソッド>#stdinstmethods]] のいずれか、または型定義で定義されたインスタンスメソッドのいずれかです。それに続く'''args'''は選択された'''method'''によって異なります。~


**標準的なインスタンスメソッド &aname(stdinstmethods); [#pc4b868a]
型定義で委譲されたインスタンスメソッド、ローカル定義されたインスタンスメソッドに加えて、全てのSnitオブジェクトは最低限次のサブコマンドも持ちます。

-''$object configure'' ? '''option''' ? ? '''value''' ? ...~
新しい値を一つ以上のオプションに割り当てます。もし引数がオプション('''option''')の名前一つだけの場合、Tkウィジェットがするように、オプションの説明のリストを返します。もし引数無しで呼び出されると、Tkウィジェットがするように、全てのオプションの説明のリストを返します。~
警告:委譲されたオプションの場合、委譲されたコンポーネントが同種の情報を返す''configure''メソッドを持っている場合のみ、情報を取得できます。~
注意:Snitは、型が最低でも一つオプションを持っている場合のみこのメソッドを定義します。

-''$object configurelist'' '''optionlist'''~
''configure''と同じですが、引数はオプションとその値のリスト一つだけです。これは型コンストラクタでは特に便利ですが、どこでも使うことができます。~
注意:Snitは、型が最低でも一つオプションを持っている場合のみこのメソッドを定義します。

-''$object cget'' '''option'''~
オプションの値を返します。~
注意:Snitは、型が最低でも一つオプションを持っている場合のみこのメソッドを定義します。

-''$object destroy''~
''destructor''を呼び出し、全ての関連するメモリを解放して、オブジェクトを破棄します。~
注意:destroyメソッドは''snit::widget''と''snit::widgetadaptor''のオブジェクトでは定義されません。これらのインスタンスは、普通のウィジェットのようにTkの''destroy''コマンドを使って破棄します。

-''$object info type''~
インスタンスの型を返します。

-''$object info vars'' ? '''pattern''' ?~
オブジェクトのインスタンス変数(Snitの内部変数は除く)のリストを返します。変数の名前は完全修飾されます。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。

-''$object info typevars'' ? '''pattern''' ?~
オブジェクトの型の型変数(Snitの内部変数は除く)のリストを返します。変数の名前は完全修飾されます。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。

-''$object info typemethods'' ? '''pattern''' ?~
型の型メソッドのリストを返します。もし型が階層的な型メソッドを持っているなら(ローカル定義されていようが委譲されていようが) 最初のトークンだけがリストに含まれます。~
もし型定義が''delegate typemethod *''を含んでいる場合、そのリストは(少なくとも一回呼び出されて型メソッドキャッシュにある)暗黙的に委譲された型メソッドの名前のみ含むでしょう。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。~
'''Snit 1.x 非互換''':Snit 1.xでは、階層化された型メソッドの(複数の単語の)完全な名前が返り値に含まれます。

-''$object info options'' ? '''pattern''' ?~
オブジェクトのオプションの名前のリストを返します。これは常に
ローカルのオプションと明示的に委譲されたオプションを含んでいます。それに加えて、もし未知のオプションが委譲されていて、その委譲されたコンポーネントがTkウィジェットのように''$object configure''で値を返すのならば、使用可能な未知のオプションも返り値に含まれます。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。~
注意:返り値は、同じ型でもインスタンスごとに違うことがあるかもしれません。なぜなら、コンポーネントオブジェクトの型は、インスタンスごとに変えることができるからです。

-''$object info methods'' ? '''pattern''' ?~
インスタンスのメソッドの名前のリストを返します。もし型が階層的な型メソッドを持っているなら(ローカル定義されていようが委譲されていようが) 最初のトークンだけがリストに含まれます。~
もし型定義が''delegate typemethod *''を含んでいる場合、そのリストは(少なくとも一回呼び出されて型メソッドキャッシュにある)暗黙的に委譲された型メソッドの名前のみ含むでしょう。~
もし'''pattern'''が与えられると''string match''パターンが使われるように、パターンにマッチした名前だけが返ります。~
'''Snit 1.x 非互換''':Snit 1.xでは、階層化された型メソッドの(複数の単語の)完全な名前が返り値に含まれます。

-''$object info args'' '''method'''~
インスタンスの'''method'''の引数の名前のリストを返します。
このメソッドは委譲された型メソッドには適用できません。

-''$object info body'' '''method'''~
インスタンスのメソッド'''method'''のボディを返します。このメソッドは委譲された型メソッドには適用できません。

-''$object info default'' '''method aname varname'''~
'''method'''の引数の'''aname'''がデフォルト値を持っているかどうか真偽値を返します。持ってる場合はTRUE、持ってない場合はFALSE。もし引数がデフォルト値を持ってる場合、変数'''varname'''にその値が代入されます。


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

-''mymethod'' '''name''' ? '''args...''' ?~
''mymethod''コマンドは他のオブジェクトに渡されるコールバックコマンドを整形するのに使われます。このコマンドは呼び出されたときに実行されるメソッド'''name'''を追加された引数を設定して返します。言い換えると、次の二つのコマンドは ''$button''が押されると、 オブジェクトの''dosomething''メソッドを実行します。
 $button configure -command [list $self dosomething myargument]
 
 $button configure -command [mymethod dosomething myargument]
この二つの大きな違いは、後者はオブジェクトのコマンド名が変更されても破綻しないというところです。

-''mytypemethod'' '''name''' ? '''args...''' ?~
''mytypemethod''コマンドは他のオブジェクトに渡されるコールバックコマンドを整形するのに使われます。このコマンドは呼び出されたときに実行される型メソッド'''name'''を追加された引数を設定して返します。言い換えると、次の二つのコマンドは ''$button''が押されると、 オブジェクトの''dosomething''メソッドを実行します。
 $button configure -command [list $type dosomething myargument]
 
 $button configure -command [mytypemethod dosomething myargument]
型コマンドの名前はリネームできません。従って実際にはこれら二つはほとんど同じです。''mytypemethod''は''mymethod''の対として提供されています。

-''myproc'' '''name''' ? '''args...''' ?~
''myproc''コマンドは他のオブジェクトに渡されるコールバックコマンドを整形するのに使われます。このコマンドは呼び出されたときに実行されるプロシージャ'''name'''を追加された引数を設定して返します。言い換えると、次の二つのコマンドは ''$button''が押されると、 オブジェクトの''dosomething''メソッドを実行します。
 $button configure -command [list ${type}::dosomething myargument]
 
 $button configure -command [myproc dosomething myargument]

-''myvar'' '''name'''~
インスタンス変数の名前を与えると、その完全修飾名を返します。変数を他のオブジェクトに渡すときに使ってください。例えば、Tkのラベルウィジェットの''-textvariable''などに渡す時など。

-''mytypevar'' '''name'''~
型変数の名前を与えると、その完全修飾名を返します。変数を他のオブジェクトに渡すときに使ってください。例えば、Tkのラベルウィジェットの''-textvariable''などに渡す時など。

-''from'' '''argvName option''' ? '''defvalue''' ?~
''from''コマンドは オプションの値をオプションと値のリスト(例えば型のコンストラクタで渡されるリストのような)から抜き出します。'''argvName'''はそのリストの変数の名前でなければなりません。'''option'''は指定されたオプションの名前です。~
''from''コマンドは'''option'''をオプションリストから探し、もし見つかれば、そのオプションとその値をリストから削除し、その値を返します。もし'''option'''が見つからなければ、'''defvalue'''を返します。もしオプションがローカル定義されたオプションで、'''defvalue'''が設定されていなければ、型定義で設定されたオプションのデフォルト値が返ります。

-''install'' '''compName''' '''using objType objName args'''...~
'''objType'''型のオブジェクトを、'''objName'''という名前で新しく作成し、[[コンポーネントと委譲>#companddelegate]]で説明されているように、 そのオブジェクトをコンポーネント'''compName'''としてインストールします。
追加の'''args...'''は'''objType'''コマンドにそのまま渡されます。もし、これが''snit::type''なら次の二つのコマンドは同じです。
 install myComp using myObjType $self.myComp args...
 
 set myComp [myObjType $self.myComp args...]
どちらのメソッドも使われていることに注意してください。'''compName'''は ''component''を使って型定義ですでに宣言されているか、 または 最低一つの'''delegate'''文から参照されていなければなりません。~
もし、これが''snit::widget''か''snit::widgetadaptor''で、オプションがコンポーネント'''compName'''に委譲されている場合、それらのオプションはTkオプションデータベースからデフォルトの値を取得するでしょう。インストールされたコンポーネントがウィジェットかそうでないかは問題ではない点に注意してください。 詳細は[[Tkオプションデータベース>#tkoptiondatabase]]を見てください。~
''install''は型コンポーネントのインストールには使うことができません。そのかわり、型コンポーネントのコマンド名を型コンポーネントの変数に割り当てるだけです。

-''installhull'' using '''widgetType args'''...
-''installhull'' '''name'''~ 
''snit::widgetadaptor''のコンストラクタはオブジェクトのhullコンポーネントになるウィジェットを作成しなければなりません。 そのウィジェットは、このコマンドを使いhullコンポーネントとしてインストールされます。インストールされたウィジェットの名前は"$win"でなければならない点に注意してください。このコマンドは二つの形式を持っています。~
最初の形式では、hullウィジェットを作成するのに、'''widgetType'''と'''args...'''(つまり、ハードコーディングされたオプションリスト) を設定します。この形式が用いられると''installhull''はhullウィジェットを作成し、Tkオプションデータベースからhullに委譲されたオプションを初期化します。~
二番目の形式では、hullウィジェットは既に作成されています。その名前は"$win"でなければならない点に注意してください。この場合、hullに委譲されたオプションはTkオプションデータベースには問い合わせをしない点に注意してください。~
長い方の形式が好ましいです。しかし、短いほうの形式はプログラマがどこでウィジェットを作成してもよいので、便利なときもあります。例えば、BWidgetのタブノートブックやページマネージャーウィジェットによって作成された"page"ウィジェットを改編するのに使うことができます。~
snit::widgetadaptorとオプションデータベースに関する詳細は[[Tkオプションデータベース>#tkoptiondatabase]]を見てください。

-''variable'' '''name'''~
普通は、インスタンス変数は型定義においてオプションやメソッドなどと一緒に定義されます。そのようなインスタンス変数は自動的に全てのインスタンスコードで可視になります(例えばメソッドのボディ)。しかしながら、インスタンスコードは''variable''コマンドを使って、型定義には現れないインスタンス変数を宣言し、そしてまた、他の名前空間から変数を現在のスコープに持ってくることができます。~
ほとんどの場合、型定義で全てのインスタンス変数を定義し、メソッドなどの中ではそれらの宣言を省略するのが最もわかりやすいです。~
これは 標準のTcl::variableコマンドの、インスタンス用の特別バージョンです。

-''typevariable'' '''name'''~
普通は、型変数は型定義においてインスタンス変数と一緒に定義されます。そのような型変数は自動的に型の全てのコードで可視になります。しかしながら、型メソッド、インスタンスメソッドなどは''typevariable''を使って、型定義には現れない型変数を宣言することができます。~
ほとんどの場合、型定義で全ての型変数を定義し、メソッドや型メソッドなどの中ではそれらの宣言を省略するのが最もわかりやすいです。~

-''varname'' '''name'''~
廃止予定。''myvar''を代わりに使用してください。~
インスタンス変数の名前を与えると、その完全修飾名を返します。変数を他のオブジェクトに渡すときに使ってください。例えば、Tkのラベルウィジェットの''-textvariable''などに渡す時など。

-''typevarname'' '''name'''~
廃止予定。''mytypevar''を代わりに使用してください。~
型変数の名前を与えると、その完全修飾名を返します。変数を他のオブジェクトに渡すときに使ってください。例えば、Tkのラベルウィジェットの''-textvariable''などに渡す時など。

-''codename'' '''name'''~
廃止予定。''myproc''を代わりに使用してください。~
proc名(型、インスタンスのメソッドではない)を与えられると、コールバックに渡すのに最適な完全修飾名を返します。


**コンポーネントと委譲 &aname(companddelegate); [#m80b1f90]
オブジェクトが他のオブジェクトを含んでいる時、例えば、ツールバーがボタンを含んでいたり、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::widget''と''snit::widgetadaptor''では、''install''コマンドは[[Tkオプションデータベース>#tkoptiondatabase]]に問い合わせることでウィジェットのオプションを適切に初期化します。

上記の例では''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''メソッドを処理しますが、''wag''は''mytail''にパスされるでしょう。''dog''にも''tail''にも存在していないメソッドの呼び出しは単純にエラーになります。

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


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

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

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


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

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

-もし''snit::widget''のデフォルトのウィジェットクラスが望んでいるものと異なる場合は、ウィジェットの定義で''widgetclass''を使って明示的に設定してください。
-オプションを定義するか、委譲したときに、デフォルトの値が望んでいるものと異なる場合は、リソースとクラス名を明示的に指定してください。
-''snit::widgetadaptor''では''installhull using''を使ってhullをインストールしてください。
-他のコンポーネントをインストールするには''install''を使ってください。

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では、全てのオプションは三つの名前を持っています(オプション名、リソース名、クラス名)。オプション名はハイフンではじまり全て小文字です。それはウィジェットの作成時、''configure''と''cget''コマンドで使われます。

リソース名とクラス名は、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"というコンポーネントに委譲されています。もしそうなら、''mywidget''は''text''ウィジェットと全て同じオプションを持っています。オプション、リソース、クラスの名前は次のとおりです。
 -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::widgetadaptor''は''installhull''をコンストラクタで呼び出さなければなりません。普通の方法では次のようになります。

 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''コマンドは次のようなことをします。
-''install''コマンドで明示的に含まれたオプションのリストを作成します(この場合は''-foreground'')。
-指定されたコンポーネントに明示的に委譲された全てのオプションをオプションデータベースに問い合わせます。
-オプションデータベースから取得したオプションとその値のリストを挿入した後に指定されたコマンドでコンポーネントを作成します。このようにして、明示的に含まれたオプション(''-foreground'')はオプションデータベースから読み込まれた値を上書きします。
-もしウィジェット定義で、''delegate option *''を使って、コンポーネントにオプションを暗黙的に委譲していたら、コンポーネントのオプションの全てのリストを取得するために、Snitは新たに作成したコンポーネントのconfigureメソッドを呼び出します。ここからSnitは明示的に''install''コマンドで含まれず、暗黙的にコンポーネントに委譲されたオプションのリストを構築します。Snitは、そのようなオプションの全てを オプションデータベースに問い合わせ、適切にコンポーネントを設定します。

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


**マクロとメタプログラミング &aname(macroandmetaprog); [#ud7aae50]
''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
 }

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

アプリケーション中の全てのSnitの型とウィジェットをコンパイルのに使われているスレーブインタプリタは一つだけなので、マクロ名が衝突する可能性があります。
Snitを使って再使用可能なパッケージを書いていて、''snit::macro''を使っているなら、それらをあなたのパッケージの名前空間で定義してください。
 snit::macro mypkg::property {name initValue} { ... }
 
 snit::type dog {
     mypkg::property mood happy
 }
これはアプリケーションの作者にとってグローバル名前空間を開けた状態にしておきます。


**検証型 &aname(validationtypes); [#e988df08]

検証型とは、特定の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''メソッドを持つオブジェクトは検証型として使うことが出来ます。新しい検証型を定義する方法は [[検証型の定義>#definevalidationtypes]]を見てください。

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

-''snit::boolean'' '''validate''' ? '''value''' ?~
-''snit::boolean'' '''name'''~ 
Tclの真偽値(1, 0, on, off, yes, no, true, false)を検証します。サブタイプを定義することができますが、オプションがありません。というのは、そうする理由が無いからです。

-''snit::double'' '''validate''' ? '''value''' ?~
-''snit::double'' '''name''' ? '''option value...''' ?~
浮動少数値を検証します。次のオプションでサブタイプを作ることが出来ます。
-- -min '''min'''~
浮動少数の最小値を指定します。値が'''min'''より小さければ不正です。
-- -max '''max'''~
浮動少数の最大値を指定します。値が'''max'''より大きければ不正です。

-''snit::enum'' '''validate''' ? '''value''' ?~
-''snit::enum'' '''name''' ? '''option value...''' ?~
値が列挙リストに含まれているかどうか検証します。基本型はそれ自身ではほとんど役に立ちません。実際は、サブタイプが検証する列挙リストを持ちます。サブタイプは次のオプションで作成されます。
-- -values '''list'''~
適正な値のリストを設定します。もし値がそのリストに含まれていれば、値は適正です。

-''snit::fpixels'' '''validate''' ? '''value''' ?~
-''snit::fpixels'' '''name''' ? '''option value...''' ?~
'''Tkプログラム専用です。''' ''winfo fpixels''によって認められたすべての形式のスクリーン距離を検証します。サブタイプは次のオプションで作成できます。
-- -min '''min'''~
最小値を指定します。もし'''min'''より小さければ値は不正です。バウンドは''winfo fpixels''によって認められた全ての形式で表現できます。
-- -max '''max'''~
最大値を指定します。もし'''min'''より大きければ値は不正です。バウンドは''winfo fpixels''によって認められた全ての形式で表現できます。

-''snit::integer'' '''validate''' ? '''value''' ?~
-''snit::integer'' name ? '''option value...''' ?~
整数値を検証します。サブタイプは次のオプションで作成できます。
-- -min '''min'''~
整数の最小値を指定します。'''min'''より値が小さければ不正です。
-- -max '''max'''~
整数の最大値を指定します。'''min'''より値が大きければ不正です。

-''snit::listtype'' '''validate''' ? '''value''' ?~
-''snit::listtype'' name ? '''option value...''' ?~
Tclリストを検証します。サブタイプは次のオプションで作成できます。
-- -minlen '''min'''~
最小のリスト長を指定します。リストの要素が'''min'''より少なければ不正です。デフォルトは0です。
-- -maxlen '''max'''~
最大のリスト長を指定します。リストの要素が'''max'''より多ければ不正です。
-- -type '''type'''~
リスト要素の型を指定します。'''type'''は検証型か検証型のサブタイプの名前でなければなりません。次の例では、-numbersの値は整数のリストでなければなりません。
 option -numbers -type {snit::listtype -type snit::integer}
このオプションは、オンザフライに新しい検証型のサブタイプを定義することをサポートしていない点に注意してください。つまり、次のコードは動かないでしょう。
 option -numbers -type {
     snit::listtype -type {snit::integer -min 5}
 }
そのかわりに、明示的にサブタイプを定義してください。
 snit::integer gt4 -min 5
 
 snit::type mytype {
     option -numbers -type {snit::listtype -type gt4}
 }

-''snit::pixels'' '''validate''' ? '''value''' ?~
-''snit::pixels'' name ? '''option value...''' ?~
'''Tkプログラム専用です。''' ''winfo pixels''によって認められたすべての形式のスクリーン距離を検証します。サブタイプは次のオプションで作成できます。
-- -min '''min'''~
最小値を指定します。もし'''min'''より小さければ値は不正です。バウンドは''winfo pixels''によって認められた全ての形式で表現できます。
-- -max '''max'''~
最大値を指定します。もし'''min'''より大きければ値は不正です。バウンドは''winfo pixels''によって認められた全ての形式で表現できます。

-''snit::stringtype'' '''validate''' ? '''value''' ?~
-''snit::stringtype'' name ? '''option value...''' ?~
Tcl文字列を検証します。基本型はそれ自身ではほとんど役に立ちません。なぜならばTclの値というのは適正な文字列だからです。サブタイプは次のオプションで作成できます。
-- -minlen '''min'''~
文字列の最小の長さを指定します。もし'''min'''文字よりもすくなければ、値は不正です。デフォルトは0です。
-- -maxlen '''max'''~
文字列の最大の長さを指定します。もし'''max'''文字よりも多ければ、値は不正です。デフォルトは0です。
-- -glob '''pattern'''~
''string match''のパターンを設定します。もしパターンにマッチしなければ、値は不正です。
-- -regexp '''regexp'''~
正規表現を指定します。もし正規表現にマッチしなければ、値は不正です。
-- -nocase '''flag'''~
デフォルトでは-globと-regexpはどちらも大文字と小文字を区別します。もし-nocaseがTRUEに設定されると、-globと-regexpは大文字と小文字を区別しなくなります。

-''snit::window'' '''validate''' ? '''value''' ?~
-''snit::window'' '''name''' ~
'''Tkプログラム専用です。''' Tkウィンドウの名前を検証します。値は''winfo exists''でtrueを返さなければなりません。そうでなければ、値は不正です。''snit::window''のサブタイプを定義することが可能ですが、現在のところ特に必用な理由もないので、オプションはありません。


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

その次に簡単な方法は、検証型コマンドとして新しい検証型を作成することです。検証型は''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''とその他の型の完全な実装をそこで見ることができます。自分で検証型を作成するときに参考にすることができます。


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

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

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


*既知のバグ [#c0db3176]
-Snit 1.xによるエラーのスタックとレースはとても読みにくく、Snitの内部情報を含みすぎています。エラーメッセージはSnit2.2でさらに改善されています。
-SourceForgeのTcllibのトラッカーを見てください。snitカテゴリです。~
http://sourceforge.net/projects/tcllib/


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


*クレジット [#y82c5a4b]
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.  もし誰か忘れていたらごめんなさい。知らせてくれたらお名前をリストに追加するつもりです。


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

----
[[CategoryTclTk]]

|New|Edit|Diff|History|Attach|Copy|Rename|
HTML convert time: 0.004 sec.