せかいや

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

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

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

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


 

P310 Object#sendメソッドは、インスタンス変数でも使える

(注)---------------------------------------------\
以下の記事はインスタンス変数について理解に誤りがあります。
正しい理解はこちら⇒http://sekai.hateblo.jp/entry/2013/08/21/073111
ただし、この記事はあくまで「パーフェクトRubyをよんだ読者の軌跡」を記録しているので、以下は修正しません。
\--------------------------------------------------

 

class MailSender
	attr_reader :from
	
	def initialize(from)
		@from = from
	end
	
	def send(to)
		"send mail: #{to}"
	end
end

ms = MailSender.new('tanaka')

p ms.send 'hoge'  ←"send mail: hoge"

p ms.__send__ :from         ←"tanaka"

p ms.instance_variable_get :@from  ←"tanaka"

最初はこの「ms.__send__ :from」ってところ、誤植かと思いました。
だって、fromメソッドなんてないよ?
「p ms.instance_variable_get :@from」は自分で追加した一行。
インスタンス変数の場合は、instance_variable_get と __send__ が同じ挙動なんだ。

本にも

Object#send はメソッドの可視性に拘らずメソッドを呼ぶことが可能です

と書いている。
例でコードを書くなら、インスタンス変数の場合もsendメソッドが使えるよ、
と一言欲しかったなあ。

ここらへん、したり顔で「インスタンス変数もメソッドの一部、
つまりはオブジェクトと考えられるわけです。」とか出てきそう。
いや知らんけど(今は)。

うーん。Ruby。奥深いぞ。
自分はまだまだ、オブジェクト指向の理解が足りてないなー。

 

P330 初めての問題

what_methods っていう面白いgem(ってなんだ?まだ出てきてないぞ)があるよ。
ここまで読んだ人なら分かるから、実装してみてね。
と書いてある。

はい。
やります。

当然(?)require の仕方、installの仕方が分からず実行できない。
本家のソースがgithub上で公開されているので、それを答えにする事にする。
https://github.com/BMorearty/what_methods/blob/master/lib/what_methods.rb


■作ったコード ※ざっくり作ってます

class Object

	def what?(after, *args)
		WhatMethods.find(self, after, *args)
	end
end

class WhatMethods

	def self.find(before, after, *args)
		res = before.methods.
			select {|name| before.method(name).arity.abs <= args.size}.
			select {|name| 
						begin
							before.clone.method(name).call(*args) == after;
						rescue Object;
						end
					}
	end
end

p "jjjj".what?("jjj")
p "jjj".what?("JJJ")

■実行結果

jjjj[:chop, :chop!]
jjj[:upcase, :swapcase, :upcase!, :swapcase!]


 

初めてRubyコードを書いて学んだこと

  • Arrayクラスのselect メソッドは便利。
  • インデントのつけ方が微妙になっちゃう。
  • rescue Object ってずるい。真面目に考えて解答見たら、この書き方だった。
  • Objectクラスを上書きできるのが、新鮮。
  • 出力結果にレシーバ文字列が表示されているのはString#display メソッドが実行されているから。
  • 解答の元のコードは、可変長引数の場合が全く考慮されてないのが心配だ(arityメソッドが負の時の分岐がない)


メタプログラミング、けっこう分かりやすいかもー。