「AUTOLOADって他でどうやるの?」
を受けて、
「メソッド名自動生成」
というのがあったのだけど、これはメソッドを動的に定義するわけではないので、メソッドを動的に定義する版も「メソッド名自動生成」の例をベースに書いてみた。
class AsciiChar
def method_missing(method, *args)
p "#{method}" if $DEBUG # (1)
self.class.instance_eval{
define_method(method){ method.to_s.sub(/^_/, "").hex.chr }
}
__send__(method)
end
end
a = AsciiChar.new
print a._72
print a._75
print a._62
print a._79
print a._63
print a._6F
print a._72 # => "ruby -d" のとき(1)は実行されない
文字列などからメソッドの定義が動的に行えて、その定義内でスコープ外の変数を参照できる言語であればどれでもできそう。
ちなみに、TDP4Rの新しいルールの書き方でも同じようなことをしている。
また、別の方法としてModuleを新しく作り、そのModuleを新たに卒存クラスへincludeするという方法も使える。
class AsciiChar
def method_missing(method, *args)
p "#{method}" if $DEBUG
m = Module.new{
module_eval{
define_method(method){ method.to_s.sub(/^_/, "").hex.chr }
}
}
self.class.class_eval{ include(m) }
__send__(method)
end
end
a = AsciiChar.new
print a._72
print a._75
print a._62
print a._79
print a._63
print a._6F
print a._72
print a._75
print a._62
print a._79
print a._63
print a._6F
b = AsciiChar.new
print b._72
print b._75
print b._62
print b._79
print b._63
print b._6F
ここで、bはaとは別に新しく作ったオブジェクトであるが、クラスに対してメソッドを定義しているので(1)のコードは実行されない。これに対して、オブジェクト毎にメソッドを定義するためには、includeではなくextendを使う。
class AsciiChar
def method_missing(method, *args)
p "#{method}" if $DEBUG
m = Module.new{
module_eval{
define_method(method){ method.to_s.sub(/^_/, "").hex.chr }
}
}
extend(m)
__send__(method)
end
end
a = AsciiChar.new
print a._72
print a._75
print a._62
print a._79
print a._63
print a._6F
print a._72
print a._75
print a._62
print a._79
print a._63
print a._6F
b = AsciiChar.new
print b._72
print b._75
print b._62
print b._79
print b._63
print b._6F
以上のことは、一応マニュアルを見れば分かることだったりする。
posted by ttate at 17:18|
Comment(0)
|
TrackBack(1)
|
Ruby
|

|