RubyCocoa の new を考える
RubyKaigi 自体の日記は書くの時間かかりそうなので、とりあえずこの件を先に。藤本さんのセッション中に irc でちょろっと出ていたけれど、RubyCocoa の Cocoa クラスにはインスタンスを生成する new メソッドがない。というかエラー。
% irb -r osx/cocoa irb(main):001:0> OSX::NSURL.new RuntimeError: use 'alloc.initXXX' to instantiate Cocoa Object from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/o sx/objc/oc_import.rb:251:in `new' from (irb):1
これは Ruby と Cocoa オブジェクトの初期化の手続きや、initXXX のそれぞれに対応して Object#initialize() を調整するのが手間がかかるってあたりが理由(だと思う)。
でも Ruby なら new したいよな。ただでさえ Cocoa のメッセージ名長いし。で、考えてみたのだけれど、欲しいところから順に CocoaClass.new を定義していけばよいんじゃなかろうか。正月にリファレンスマニュアルの作業してて、クラスメソッド new を定義してあるのを見たときは驚いたけど、定義したからって問題があるわけじゃない。
Hash をキーワード引数的に受け取るのがいいのかな。たとえば、
class OSX::NSView # - :frame : ビューの位置、大きさを NSRect で def self.new(args = {}) args[:frame] ||= NSMakeRect(...) # 省略されたら適当な初期値を self.alloc.initWithFrame(args[:frame]) end end class OSX::NSWindow # - :contentRect # - :styleMask # - :bufferingType # - :defer # - :screen def self.new(args = {}) args[:contentRect] ||= NSMakeRect(...) args[:styleMask] ||= NSTitledWindowMask & NSClosableWindowMask & NSMiniaturizableWindowMask args[:bufferingType] ||= NSBackingStoreBuffered args[:defer] ||= true args[:screen] ||= nil # メインスクリーン self.alloc.initWithContentRect_styleMask_backing_defer_screen(...) end end
こんな感じ。適切な初期値を考えるのがちょっと大変かもしれないけれど、引数の多い初期化メソッドが少なくない Cocoa では有効かもしれない。初期値が気に入らなければインスタンスを生成した後で、setter で値を変更すればいいだけだし。
| 固定リンク
最近のコメント