Snitの特徴は以下の通りです。
それでは、Snitの使い方を説明します。
package require snit ::snit::type Hello { variable var {Hello World} method print {} { puts $var } } |
インスタンスの生成は以下の様にします。
# インスタンスの作成(その1) Hello create foo => ::foo # インスタンスの作成(その2) Hello foo => ::foo # インスタンスの作成(その3) Hello foo%AUTO% => ::fooHello1 |
インスタンスとタイプの破棄は以下の様にします。
# インスタンスの生成 Hello foo # インスタンスの破棄 foo destroy # タイプとインスタンスの破棄 Hello destroy |
package require snit ::snit::type Hello { variable var {Hello World} method print {} { puts $var } } # インスタンスの作成 Hello foo # 強引な変数のアクセス puts $::Hello::Snit_inst1::var => Hello World |
一方、メソッドはサブコマンドのようにアクセスします。
# インスタンスの作成 Hello foo # メソッドのアクセス foo print => Hello World |
package require snit ::snit::type Hello { variable var {Hello World} # privateなメソッド proc doprint {selfns} { variable var puts $var } # publicなメソッド method print {} { doprint $selfns } } # インスタンスの作成 Hello foo # メソッドのアクセス foo doprint '::foo doprint' is not defined. # 強引なメソッドのアクセス ::Hello::doprint ::Hello::Snit_inst1 => Hello World # メソッドのアクセス foo print => Hello World |
メソッドからメソッドを呼び出すには、呼び出すメソッドの第1引数にnamespace名を渡す要があります。
※ selfns変数はnamaspace名になります。この場合、$selfnsの内容は::Hello::Snit_inst1になります。
staticなメソッドを定義するには、typemethodを使います。
staticなメソッドの呼び出しにインスタンス名は必要としません。
staticなメソッドは、タイプのサブコマンドとして呼び出します。
package require snit ::snit::type Count { # staticなメンバ typevariable count 0 # staticなメソッド typemethod print {} { puts "$type = $count" } # publicなメソッド method incr {} { incr count } } # インスタンスの作成 Count foo1 Count foo2 # publicなメンバの呼び出し foo1 incr => 1 foo2 incr => 2 # staticなメンバの呼び出し Count print => ::Count = 2 |
※ type変数はタイプ名になります。この場合、$typeの内容は::Countになります。
package require snit snit::type Hello { # デフォルト・コンストラクタ constructor {args} { $self configurelist $args puts start } # デストラクタ destructor { puts end } } # インスタンスの生成 Hello foo => start => ::foo # インスタンスの破棄 foo destroy => end |
引数を持つコンストラクタも定義できます。
package require snit snit::type Hello { variable data constructor {breed color} { set data(breed) $breed set data(color) $color } } # インスタンスの生成 Hello foo labrador chocolate => ::foo |
package require snit ::snit::type Hello { variable var_english {Hello!} variable var_japanese {こんにちは!} option -lang english method print {} { if {$options(-lang) == "english"} { return $var_english } else { return $var_japanese } } onconfigure -lang {lang} { if {$lang != "english"} { set options(-lang) japanese } else { set options(-lang) english } } } # インスタンスの生成 Hello foo1 foo1 print => Hello! # インスタンスの生成(オプション付き) Hello foo2 -lang japanese foo2 print => こんにちは! |
options配列変数は、オプション用のメンバです。オプションの状態を保持します。
onconfigureはオプション設定時に呼び出されるオプションハンドラを定義します。
oncgetというオプション参照時に呼び出されるオプションハンドラも定義できます。
どちらのオプションハンドラも省略可能です。
package require snit ::snit::type Hello { variable var {Hello World} method print {} { after 1000 {puts $var} } } Hello foo foo print |
解決策としては、codenameコマンドでnamespaceを事前に解決したコードを生成する方法です。
package require snit ::snit::type Hello { variable var {Hello World} method print {} { set cmd [list [codename doputs] $selfns] after 1000 $cmd } # private method proc doputs {selfns} { puts $var } } Hello foo foo print |
この時、事前に解決したコード($cmd変数の内容)は以下の様になります。
codenameコマンドは、指定されたnamespaceで引数のコマンドを実行します。
::Hello::doprint ::Hello::Snit_inst1 |
もし、上記doputsメソッドがpublicなメソッドの場合は、以下のように記述します。
package require snit ::snit::type Hello { variable var {Hello World} method print {} { set cmd [list $self doputs] after 1000 $cmd } # public method method doputs {} { puts $var } } Hello foo foo print |
この時、事前に解決したコード($cmd変数の内容)は以下の様になります。
self変数は、指定されたnamespaceで引数のコマンドを実行します。
::foo doputs |
package require snit ::snit::widgetadaptor pushbutton { # オプションの追加 option -ison 0 # コンストラクタ constructor {args} { installhull [checkbutton $win -indicatoron no \ -padx 5 -pady 5 -onvalue 1 -offvalue 0 \ -variable [list $selfns]::options(-ison)] $self configurelist $args } # メソッドの追加 method ison {} { return $options(-ison) } # メソッドとオプションの委任 delegate method * to hull delegate option * to hull } pack [pushbutton .pb -text Push -command { tk_messageBox -message [list [.pb cget -ison] [.pb ison]] }] |
押すと引っ込んだままになるpushbuttonボタンができました。
ボタンの状態をisonコマンドまたは-isonオプションで確認できます。
→