せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】パーフェクトRuby 学習感想文 ~第9章

それでは9章を読んでいきます。

(参考・経緯など)
パーフェクトRuby 学習感想文 ~はじめに

 
初めての突っ込みゼロの章。おめでとうございます。


調子にのってすみません・・。怒らないでください


 

感想

Procオブジェクトが面白い。
レシーバーなのにメソッド定義も持っている、って感じ?

double = Proc.new{|x| x*2}
p double.(1)  ←2


 

トップレベルメソッドの実行レシーバーは何?

ちょっとはまった。


当然実行できる↓

def kore(x)
	x * 3
end

p kore(1)  #3

self.kore にするとエラーになる↓

def kore(x)
	x * 3
end

p self.kore(1)  #エラー。`<main>': private method `kore' called for main:Object

うーん。Objectクラスインスタンスではkoreメソッドを見に行けませんってことかな。private?
トップレベルのメソッドは暗黙的にselfがレシーバーだと思ってたのに。
なら何がレシーバーなんだ?


トップレベルself のクラスを確認
def kore(x)
	x * 3
end

p self.class.ancestors  ←[Object, Kernel, BasicObject]
p kore(1)  

予想通りです。


トップレベルメソッド内のself のクラスを確認
def kore(x)
	p self.class.ancestors ←[Object, Kernel, BasicObject]
	x * 3
end

p kore(1)  

うーん? self.kore でもいけそうな気がするけど?


???

やっぱり「レシーバーが省略されるとselfがレシーバとなる」で正しいみたい。
なのになぜ self.kore(1) はエラーになるの?


正解:private メソッドはレシーバを省略するかたちでしか呼び出せない

P120に書いていました。
そうなのですね。だからself.kore() はエラーになったのですね。

なら、本当にkore がprivateメソッドとしてObjectクラスに登録されているか
しらべてみましょう。


Objectクラスのprivateメソッド一覧
def kore(x)
	x * 3
end

p self.class.private_instance_methods
p kore(1)  

実行結果

[:kore, :initialize_copy, :initialize_dup, :initialize_clone, …
3

おー。koreメソッドがあるぞー。

つまりkore メソッドは、selfオブジェクトの特異メソッドってことか。

P245にこう書いてある↓

特異メソッドを定義した際に、
その特異メソッドが定義されるクラスが特異クラスです。

つまり、selfはObjectクラスのインスタンスだと思っていたけど、正確には
「selfはObject特異クラスのインスタンス」って事か?確認してみよう。


 

selfはObject特異クラスのインスタンス
def kore(x)
	x * 3
end

p self.class.method_defined? :kore                    ←false
p self.singleton_class.method_defined? :kore          ←false
p self.singleton_class.private_method_defined? :kore  ←true

p self.singleton_class   ←#<Class:#<Object:0x4aef98>>


なるほどー。