永井@知能.九工大です.

From: AkihitoWatanabe <watanabea0611 / cap.bbiq.jp>
Subject: [ruby-list:46214] Ruby/Tkについての質問
Date: Thu, 16 Jul 2009 16:04:49 +0900
Message-ID: <23BEEE81-1022-4BD5-A874-438B4B689515 / cap.bbiq.jp>
> TkLineをスーパークラスとして新規クラスを定義した場合に
>   uninitialized constant TkcLine (NameError)
> というエラーがでます。どうしてでしょうか。
> 色々調べてみたのですが、分かりません。
> TkBottunをスーパークラスとして作成したクラスを定義した場合には
> 問題はありませんでした。

この問題については,より新しいバージョンの Ruby/Tk では修正済みです.
まず先に回避策を述べた上で,なぜそうなっているのかを説明します.

回避策としては,"require 'tk'" の後に 
"require 'tk/canvas'" を加えてください.
そうしたものを問題修正済みの Ruby/Tk で実行しても問題はありません.

Ruby/Tk 全体は結構大きなものですので,
使いもしないウィジェットのための定義をすべて読み込んだりいると
大変なことになります.
そのため,autoload の機構を利用して,クラスが最初に参照されたときに
必要ファイルを require するようになっています.
ご利用の Ruby のバージョンがいくつかはわかりませんが,
多分 <rubyライブラリ>/tk/autoload.rb というファイルがあるはずです.
このファイルで基本の autoload 定義がなされています.
たとえば "class FUGA < TkButton" とすると,
この時点で TkButton クラスが参照されていることになり,
autoload によって tk/button.rb が読みこまれ,
TkButton クラスが定義されるということになります.

で,古いバージョンのものでは,TkCanvas についての autoload 定義は
なされていたのですが,キャンバスアイテムの定義がありませんでした.
キャンバスアイテムの定義は TkCanvas の定義を行っているファイルと
同一のファイル中で行っているため,手抜いていたわけです.
キャンバスアイテムを使うためにはキャンバスオブジェクトが必要だから,
TkCanvas クラスが参照された時点で読み込まれるだろうと考えたわけです.

ですが,canvas ウィジェットを生成する前に
キャンバスアイテムのサブクラスを新たに定義しようとした場合,
TkCanvas に対する autoload が働いていませんから
キャンバスアイテムクラスが定義されていないというエラーになります.
よって "require 'tk/canvas'" というように
明示して読み込んでやる必要があります.

新しいバージョンのものでは tk/autoload.rb に
キャンバスアイテムクラスも加えられましたので,
キャンバスアイテムのサブクラスを定義しようとした際に
tk/canvas.rb が読み込まれて定義されるため,問題は生じません.
-- 
永井 秀利  (nagai / ai.kyutech.ac.jp)
九州工業大学 大学院情報工学研究院 知能情報工学研究系 知能情報メディア部門