Rubyで動的に関数定義2  [ruby]  [tips]

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)