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オプションで確認できます。
→