web Rubyで動的に関数定義
からの続き。
生成後のインスタンスに関数を動的に生やす場合は、いろいろ試したが、以下の方法が一番よさそう。
インスタンス変数、クラスインスタンス変数、ローカル変数(クロージャ)が利用できる。
class Dog
@dog_counter = 0
def initialize(name)
self.class.class_eval { @dog_counter += 1 }
@dog_name = name
end
def perform
puts "*****"
puts "I am #{@dog_name}." # instance variable @
puts "Total Dogs are #{self.class.class_eval {@dog_counter}}." # class instance variable @
puts "bow!"
end
end
dog_hoge = Dog.new('hoge')
dog_hoge.perform
dog_fuga = Dog.new('fuga')
dog_fuga.perform
インスタンスdog_fugaにだけ関数をオーバライドしてやる。
instance_eval, define_methodを利用することにより、外部ローカル変数を利用できる。
lexical_local_variable = 'Wooooo!'
(class << dog_fuga;self;end).instance_eval do
define_method(:perform) do
puts "*****"
puts "I am #{@dog_name}." # instance variable @
puts "I am one of the #{self.class.class_eval {@dog_counter}} Dogs." # class instance variable @
puts "#{lexical_local_variable}" # lexical closure(local variable)
end
end
dog_hoge.perform
dog_fuga.perform
いろいろ使えそうだ。
追記
Rubyで動的に関数定義3(for Test::Unit)
ツイート