|
Tclのオブジェクト指向拡張: [incr Tcl] Tcl/Tkを使うと数十〜数百行の小さなウィンドウアプリケーションを驚くほど高速に開発することができます。 それはTclがインタープリタ型言語処理系であるということ以外にも、 なんでも文字列として連結してコマンドを作り上げることができる柔軟性、 言語規則が堅苦しくなく例外や制約が少ない特異ではありますが平易な文法によるところが大きいといえます。 しかしこれらの特徴が大きく裏目に出て、 1000行を超える規模のアプリケーションになると Tcl/Tk のコードは非常に読みづらく、理解しにくくなります。 上記の特徴の反動として、多発されるグローバル変数、 階層化できないデータ構造などの弊害により、 大規模なTclコードはさながら迷路のようになっていて、 容易にデバッグもできない状態になってしまうからです。 このような欠点は比較的初期からコミュニティに認識されていたため、 これを補うべくTcl言語の基本構文にオブジェクト指向 (以後たびたびOO(Object Oriented)と略すことにします) の概念を導入する拡張パッチ(*1)も早くからいくつか現れていましたが、 その中で最も有名なものが [incr Tcl] です。 1990年代、 Tcl/Tkの普及と共にいろいろな用途へのTcl/Tkの適応が模索されるようになると、 [incr Tcl]はますます広く支持されるようになり、 世界中で最もポピュラーなTcl拡張のひとつとなりました。 その結果、1997年に現れたTcl/Tkの本体処理系バージョン8.0では、 [incr Tcl]の名前空間(namespace)の概念が本体に「逆輸入」され、 データやコードの構造化という面で大きな寄与をしました。 [incr Tcl]はその名前からも分かるように、C++のOOを色濃く受け継いでいます。 クラスとインスタンス、インスタンス変数、メソッド、 public/protected/private、コンストラクタとデストラクタ、 継承と多重継承といった概念を用語も含めて非常に忠実にTcl言語に「覆い被せて」 おり、たかがTclとあなどって実際に書いてみるときっと驚かれると思います。 (*1)その後、[incr Tcl]の認知が広まるにつれ、 Tcl/Tk本体の開発陣も「配慮」を見せるようになり、 現在では本体ソースを改造する「パッチ」ではなく、 本体に手を加えることなく使える拡張ライブラリになっています。
Python/Tkinterはどうだ! Tclと並んで、 Tkを標準GUIライブラリとするスクリプト言語はもうひとつありまして、 それが他でもない超高級OO言語のPythonです。 Pythonも原開発陣がUNIX版とWindows版を並行して公開しており、 そのオリジナルの配布アーカイブに既にTkのGUIを使うモジュール(Tkinter) が含まれているなど、Tclとよく似た現状です。 Pythonは完成度の高いOOを実現しており、 しかもTclと同様インタープリタ言語の気軽さ、 GUIアプリケーション開発の面白さも備えた、OOの入門用としてぴったりの言語です。 もしTclにこだわらずOOにこだわるなら、 [incr Tcl]でなくPython/Tkinterを使うというのもひとつの道だと思います。 むろん、Tkにもこだわらないのであれば、Javaという選択シもあります。
[incr Tk]と[incr Widgets] [incr Tcl]の仲間に[incr Tk]と[incr Widgets]があります。 [incr Tk]は[incr Tcl]のTk版か、というと、 おおむねその通りですが、そう単純なわけではありません。 [incr Tcl]しか使っていなくても、 [incr Tcl]のOO文法だけで標準TkのGUI部品を使ってウィンドウアプリケーションが書けるので、 そうなると[incr Tk]はなんなんだ、 ということになりますね。 [incr Tk]は、[incr Tcl]のOO文法を使って、 標準Tk部品を組み合わせた複雑なGUI部品を[incr Tcl]クラスとして定義するためのフレームワークです。 たとえばスクロールバーのついたテキストは、普通標準Tkでは
frame .f
scrollbar .f.scrv -orient vertical \
-command ".f.txaa yview"
text .f.txaa -font fixedsys -width 60 \
-yscrollcommand ".f.scrv set"
pack .f.txaa .f.scrv -side left -fill y
のように書きますが、これを例えば ScrolledText という[incr Tcl]クラスとして定義しておいて
ScrolledText .st -font fixedsys -width 60 pack .stとすればすごく楽にこのようなGUIを出すことができるようになります。 この「[incr Tcl]クラスとして定義しておく」、ということをするのが [incr Tk]というわけです。 さらに、この[incr Tk]の開発陣自身が、 [incr Tk]を使って実際に複数のGUI部品からなるよく使う複雑な GUI部品を作ってコレクションというかライブラリにしてしまったのが [incr Widgets]です。 上のScrolledTextの例でもわかる通り、いったんクラスになった GUI部品を使うだけなら、Tcl言語と書き方はほとんど同じです。 ですから、 [incr Widgets]の便利なGUI部品を使うだけなら、 [incr Tcl]のOO文法も[incr Tk]のフレームワーク記述も知る必要はありません。 このようなGUI部品を自分でも作りたい場合は、 [incr Tk]のルールに沿ってクラス定義を書く必要があり、 当然[incr Tcl]のOO文法の知識も必要になります。
[incr Tcl]のインストール [incr Tcl]はTcl/Tkの拡張パッケージとして最も有名で、 最も普及しているライブラリのひとつです。 [incr Tcl]はTclTk.comにある総本山 から最新の版が入手できます。 UNIX用には[incr Tcl]、[incr Tk]、[incr Widgets]それぞれに独立したソースアーカイブが、 Windows用にはコンパイル済でTcl/Tk、[incr Tcl]、[incr Tk]、[incr Widgets] が一緒になった自己解凍書庫が配布されています。 なお[incr Tcl]はしばしばItcl、[incr Tk]はしばしばItk、 [incr Widgets]はしばしばIwidgets と略記されます。ちなみに「[」と「]」は一般には発音しない文字と思われていて、 マニュアルでは[incr Tcl]は「いんくりめんとてぃくる」または「いんかーてぃくる」 と発音する、とされています。 [incr Tk]は「いんかーてぃーけー」でしょうか。 [incr Tcl]はTcl言語の完全上位互換で、[incr Tcl]のインタープリタ (解釈実行系)は純粋なTcl言語のコードも実行できます。
●Windows(95,98,NT)へのインストール package require Itcl package require Itkと書いておいてからwishで呼び出すと、 [incr Tcl]対応のOO文法が理解してもらえるようになります。 itkwish31.exeで普通のTcl/Tkのスクリプトを実行させることもできます。 なお、Windowsでは[incr Tcl]スクリプトに「.itk」 という拡張子をつけると、エクスプローラでダブルクリックするだけで itkwish31.exeで解釈実行してもらえます。
[incr Tcl]のとっつきぶぶん [incr Tcl]のOO文法は次のページからレビューしていこうと思いますが、 まずはサンプルです。
# 当然、コメントなどのスタイルはTclと同じです。
class Hello {
variable w
variable Colors {red green blue #600060 #006060 #606000}
variable CurIndex 0
constructor {toplevel title message} {
set w $toplevel
toplevel $w
wm title $w $title
label $w.laba -text $message -fg [lindex $Colors $CurIndex]
frame $w.fa
button $w.fa.cmda -text Push -command "$this changeColor"
button $w.fa.cmde -text Close -command "delete object $this"
pack $w.fa.cmde $w.fa.cmda -side right
pack $w.laba $w.fa
}
destructor {
destroy $w
}
method changeColor {} {
incr CurIndex
if {$CurIndex == 6} {set CurIndex 0}
$w.laba configure -fg [lindex $Colors $CurIndex]
}
}
Hello he .hello "Demo Demo" "Hello, World"
# end.
さてまずはクラスありき。[incr Tcl]でもクラスはclass「コマンド」 で定義します。具体的には、ひとつのクラスをclassコマンドの第2引数として、 { }で大きく囲みます。第1引数はクラスの名前です。 variableコマンドはいわゆるクラス変数(メンバ変数) を宣言または初期化するものです。 変数名の後ろに引数をつけると、その値で初期化されます。 Tcl/Tkが[incr Tcl]から 「逆輸入」したTcl言語自身のvariableコマンドとは少しだけ使い方が違うので混乱しないように注意しないといけません。 constructor、destructor がそれぞれおなじみのコンストラクタ、デストラクタです。 destructorは引数をとれないのもC++のデストラクタやJavaのファイナライザと同じですね。 インスタンス化は Hello he .hello "Demo Demo" "Hello, World"こんな感じでやっていますが、これはJava風に書くと Hello he = new Hello(.hello, "Demo Demo", "Hello, World");こんな感じになりましょう。 heがインスタンス名ですが、 [incr Tcl]ではインスタンス名はTcl変数とは別の空間で管理されるので、 Tcl変数と[incr Tcl]インスタンスをまぜこぜにすると混乱しがちなので、 注意しないといけません。 それでは次のページから[incr Tcl]のOO文法をあまり堅苦しくないように気楽にレビューしていこうと思います。 |