From: Masahiro S. ()
<sa...@to...> - 2003-10-27 16:04:55
|
さかいです。 From: Masao Mutoh <mu...@hi...> Subject: Re: [ruby-gnome2-devel-ja] Re: [ruby-gnome2-devel-ja] GLibのregister_type周辺 Date: Mon, 27 Oct 2003 01:32:32 +0900 > むとうです。 > > On Sun, 26 Oct 2003 01:00:45 +0900 (JST) > Masahiro Sakai (酒井政裕) <sa...@to...> wrote: > > > さかいです。 > > > ではとりあえずサンプルを。 > > > > require 'gtk2' > > Gtk.init > > > > class MyButton < Gtk::Button > > register_type("MyButton") > > > > def initialize(label = nil) > > # XXX: register_typeするとsuperがGLib#initialize相当になる 訂正。GLib#initializeではなくGLib::Object#initializeです。 > なるほど。これは良いアイデアだと思います。 > register_typeは活かして上記は採用と言うことで。 > > super("label" => label) > > @fuga = 0 > > end > > > # 既存のシグナルのデフォルトハンドラをオーバーライド > > def do_clicked(*args) > > puts "MyButton#do_clicked enter" > > #p caller > > super > > puts "MyButton#do_clicked leave" > > end > > # 新しいシグナルを定義 > > signal_new("hoge", # 名前 > > GLib::Signal::RUN_FIRST, # フラグ > > nil, # accumulator (XXX: 仕様が未確定) > > GLib::Type["void"], # 返り値の型 > > GLib::Type["gint"], GLib::Type["gint"] # 引数の型 > > ) > > # 新しいシグナルのデフォルトハンドラ > > def do_hoge(a, b) > > puts "MyButton#do_hoge enter" > > #p caller > > puts "MyButton#do_hoge leave" > > end > > たぶん、私が"Rubyっぽく"とお願いしたからだとは思うのですが > 以下の点が気になります。 > ・メソッド定義の形になっている。 > 他のメソッドと用途がかなり違う。また、 > signal_connect()みたいブロックを受け付ける形とも違う > ・do_*の名前がちと汎用的すぎるような...。 do_*は私も一般的すぎる名前だと感じてたので、 以下の提案にあるように、signal_do_*という名前にしようと思います。 > ・signal_overrideのdo_clickedが突然現れ、do_clickedの意味が > ちょっとわかりづらい気がする。 > #もちろん、register_typeを知ってれば気にならないと言う人 > #もいるとは思いますが。 > 逆に、以下のような記法はどうでしょうか。 > > signal_override("clicked") {|args,...| > : > super > : > } > signal_new("hoge", ..... ){|args,...| > : > } > これでdo_*のようなメソッドを定義する必要もなくブロック内の > ロジックの使用用途が見た目上、限定できるような気がします。 現在のRubyでやろうとすると、以下のような問題点があるので、 おそらく無理です。 * メソッドにしないとsuperを横取りできない * ブロックで、selfをすげかえて、かつ引数を渡す方法が現状のRubyでは 提供されていない。(例外はdefine_method) http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/28277 * define_methodの振る舞いは1.6と1.8で異なるので、define_methodは実質的に使えない > 実装が難しいようでしたら、逆に以下のようにするとか。 > > signal_override("clicked") > def signal_do_clicked(args,...) > : > super > : > } > > signal_new("hoge", ..... ) > def signal_do_hoge(args,...) > : > } > もちろん、さかいさんの実装を見てしまうと、 > 上記ではsignal_override("clicked")は冗長なものに > なるとは思いますが、 > > 要は、signal_newとsignal_overrideの位置づけを同様にして > 見た目上の一貫性を持たせることを意図しています。 なるほど。 > ------- > あとそれとは別に、GLib::Typeの部分ってRubyのクラスを > 使うようにはできないですかね。 > > > signal_new("hoge", # 名前 > > GLib::Signal::RUN_FIRST, # フラグ > > nil, # accumulator (XXX: 仕様が未確定) > > GLib::Type["void"], # 返り値の型 > > GLib::Type["gint"], GLib::Type["gint"] # 引数の型 > > ) > > signal_new("hoge", # 名前 > GLib::Signal::RUN_FIRST, # フラグ > nil, # accumulator (XXX: 仕様が未確定) > nil, # 返り値の型 > Integer, Integer, # 引数の型 > ) > > 両方使えるようにするとかでも構いませんけど...。 そうですねぇ…… > > # 新しいプロパティの作成 > > install_property(GLib::Param::Int.new("fuga", # name > > "Fuga", # nick > > "fuga hoge", # blurb > > 0, # min > > 10000, # max > > 0, # default > > GLib::Param::READABLE | > > GLib::Param::WRITABLE)) > > # プロパティの実装 > > def fuga > > puts "MyButton#fuga is called" > > @fuga > > end > > def fuga=(arg) > > puts "MyButton#fuga= is called" > > @fuga = arg > > end > > end > > これって、def fugaとfuga=は必要ですか? > 上記の形でinstall_propertyを読んだら、 > 1. @fugaというインスタンス変数が定義される > 2. fuga, fuga=, set_fugaが生成される > の2つを自動で行うのが良いと思うのですがいかがでしょうか? > #実装上難しいのかな。 インスタンス変数を使って実装するかどうかはプロパティの実装者が決めることなので、 自動的に行うのは良くないと思います。 > あり? > そういえばこの場合、@fugaって定義する必要ありましたっけ? > 通常、propertiesってsetter/getterはあるけどインスタンス変数 > としては存在しないと思ってたのですが、そうではない? クラスの実装側がsetter/getterを定義します。 Cで定義されたクラスではCでsetter/getterが定義されていましたが、 Rubyでクラスを定義するのでRuby側でsetter/getterを用意します。 -- 酒井 政裕 / Masahiro Sakai |