サヨウナラ ns_import
ちょっと前にふじもとさんから聞いた、lazy import による問題を修正。これがどんな問題かっていうと、
- 現在の svn trunk (apple-unstable のマージ後) では、OSX::NSFoo とすると、const_missing を経由して、自動的に Cocoa のクラスが定義される(一種の autoload)
- じゃあ、OSX.ns_import いらねーじゃん! -> そうでもない
どういう状況で OSX.ns_import が必要なのかを説明しよう。
module OSX
class NSURL
def some_method()
end
end
end
このコードを書いた人は、きっとこんなことを考えるはずだ。
「これで OSX::NSURL クラスに some_method() という新しいメソッドを追加したぜ」
でも、そうじゃあない。ここでは OSX::NSURL という *新しい* Object のサブクラスが定義されて、そのクラスに some_method() というメソッドを定義しているだけだ。実際の Cocoa クラスの NSURL にメソッドを追加するには、class NSURL と宣言する以前に、OSX.ns_import :NSURL として名前空間に OSX::NSURL を呼び出しておかないといけない。
これじゃ、autoload の価値も半減(は言い過ぎかも)だよな。
というわけで強引に解消。ここでの作戦は、
- OSX::NSFoo といったクラスが定義されたら、ns_import したものと差し替え
というもの。ここでは、Object.inherited() をオーバーライドすることで実現した。詳しくは、svn の diff 参照。Module#const_set() でクラスの定義をフックできれば、もうちょっと簡単に書けたんだけどねえ。