2008-03-22 [長年日記]
■classという文 そして プライベートインスタンスメソッド
Rails' Wiki - Rails勉強会@東北第9回 で出た話題を復習した。
rubyはクラスを定義した時にクラスメソッドを実行することが出来て、
このin_place_edit_forはクラスメソッドなんですよ。
quintia:うわー!そうだったのかー。
2008-03-19 - 福島でRailsを使って仕事を頑張る計画
この quintia が私。
さて、「クラスを定義した時にクラスメソッドを実行することが出来て」は多分厳密には正しくないのではないかと思います。(追記)取り消して書き直しました
さて、「クラスを定義した時にクラスメソッドを実行することが出来て」の部分は当然ではあるのですが、けれどこの場合、in_place_edit_for がクラスメソッドだというのはちょっとピンときません。
レシーバが曖昧なのです。
以下復習したことをまとめてみましょう。
Rails の in_place_edit_for は敷居が高いので、
class Foo attr_accessor :foo attr_reader :bar attr_writer :baz end
の attr_accessor, attr_reader, attr_writer を考えましょう。
これは実はメソッドなのですね。(http://www.ruby-lang.org/ja/man/html/Module.html#attr_accessor 参照)
ところでRuby ではクラス定義も"文"の実行です。
class〜end でクラス定義"文"を作っているんです。
さて、クラス定義文の実行中の self、つまりメソッドの実行主体――Ruby では"レシーバ"と呼ばれますね――は何なのでしょう?
Fooクラスです。
といってもこれでは誤解を招くので噛み砕きます。
まず Foo というのは"定数"です。定数の形式を思いだしてください。"英大文字で始まること"でした。
Ruby で俗に"クラス名"と呼んでいるものの正体は、実は"定数"なのです(文法上は)。
定数Fooが指しているものは何でしょう?
Classというクラスがあります。
定数Fooは"Classクラスのインスタンス"になります。
class Foo p self.class.name # =>"Class" end
で確認できます。
(実行した時の結果を # => というコメントで表記するという慣例に従ってます)
attr_accessor は、Moduleクラスのプライベートインスタンスメソッドなのですが(先に提示したリンク先のページをよく見てください)、ClassクラスがModuleクラスを継承しているので、クラス定義式の中で使えます。
class Foo attr_accessor :foo end
を、省略されている色んなものを書き足すと、
class Foo self.attr_accessor(:foo) end
という感じになります(ただしプライベートインスタンスメソッドなので本当にこのようには書けません。"概念的にはこんな感じ"という比喩です)。
ここに書いた self は先に書いた様に定数Fooが指しているものにほかならず、それはClassクラスのインスタンスです。
だから、この場所から、プライベートインスタンスメソッドを呼び出せるのです。
そしてattr_accessor メソッドは、レシーバにシンボルと同じ名前の、最も単純な形での"呼び出しメソッド"と"代入メソッド"を作ります。
もう一度書きましょう。
attr_accessor メソッドは、"メソッドを作るメソッド"なのです。
それによって、
class Foo def foo @foo end def foo=(val) @foo = val end end
と等価になるのです。
ここまで書けば、勘のいい人は気づくのでしょうが、メソッド定義である def も"文"であって、def〜end がメソッド定義"文"になりです。
メソッド定義文内の self (レシーバ)は、Fooクラスのインスタンスです。
これはまぁ、当たり前ですね。
class Foo def foo p self.class.name #=>"Foo" end end
あとは余談。
クラス定義文もメソッド定義文も、ちゃんと値を返してくれて、変数に代入することができたりします。
nilですけどね……。
a = class Bar end p a #=> nil
class Baz a = def baz end p a #=> nil end
もしくはグローバル変数を使うと
class Baz $a = def baz end end p $a #=> nil
てな感じです。
ずっと昔には理解できていたことなのかもしれませんが、すっかり忘れていました。
Rails はこういう仕組みをバンバン使ってますよ〜、ということでした。
復習終わり。
■仮面ライダーカブト GOD SPEED LOVE 見た
というか子どもたちに見せていたというか。
時間ものは難しい。色々と目をつぶらないといけないことはあるものの、面白かった。
番外編の様でいて、本編と重なっている。重なっているようで繋がらない。
そんな微妙さがいいさじ加減。