過去の日記

2008-03-22 [長年日記]

classという文 そして プライベートインスタンスメソッド [Ruby]

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 見た [anime]

というか子どもたちに見せていたというか。

劇場版 仮面ライダーカブト GOD SPEED LOVE [DVD]

  • 監督: 石田秀範
  • 出演: 水嶋ヒロ,佐藤祐基,里中唯,徳山秀典,加藤和樹
  • 出版社/メーカー: 東映
  • ASIN: B000ION488
  • 発売: 2007-01-21
  • amazon.co.jp詳細へ

時間ものは難しい。色々と目をつぶらないといけないことはあるものの、面白かった。

番外編の様でいて、本編と重なっている。重なっているようで繋がらない。
そんな微妙さがいいさじ加減。

鋼の錬金術師 19 [comic]

鋼の錬金術師 19 (ガンガンコミックス)

  • 作者: 荒川 弘
  • 出版社/メーカー: スクウェア・エニックス
  • 発売: 2008-03-22
  • ASIN: 4757522371
  • メディア: コミック
  • amazon.co.jp詳細へ

ホーエンハイム。命。
全は一。一は全。
自分は世界。世界は自分。

……物語の終局で、兄弟が傍観者になることはなさそうな配置の仕方。
期待させてくれるなぁ。