如何在Ruby中使用给定的方法和方法体动态创建类?

时间:2011-11-24 18:05:46

标签: ruby-on-rails ruby dynamic metaprogramming

在Ruby中,您如何定义方法

def make_class(method_name, method_body, s_value)

使用以下实现

返回课程

class Anonymous
    def method_name(args)
        method_body(args)
    end

    def to_s
       return s_value
    end
end

如果你可以链接到你认为对基本的Ruby元编程有用的任何资源,那么这也是很好的。

4 个答案:

答案 0 :(得分:5)

你可以像这样使用smth:

def make_class(s_value, method_name, &method_body)    
  Class.new do   
    define_method method_name, method_body    

    define_method :to_s do    
      s_value    
    end    
  end
end    

klass = make_class 'foo instance', :foo do |*args|    
  "called foo with #{args.inspect}"    
end    

k = klass.new     
puts k.to_s                 # => foo instance
puts k.foo [1, 2], 'hello'  # => called foo with [[1, 2], "hello"]

在这种情况下,您应该将方法的主体作为块传递(您可以将|*args|替换为您希望作为参数的任何参数列表)。如果您想将method_body作为一个块而不是字符串传递,那么eval就是您的朋友。

答案 1 :(得分:2)

def make_class(method_name, method_body, s_value)
  Class.new {
    define_method method_name do |*args|
      eval(method_body)
    end

    define_method :to_s do
      s_value
    end
  }
end

"Metaprogramming Ruby: Program Like the Ruby Pros"是了解红宝石元编程的好书。

答案 2 :(得分:1)

我能想到的最简单方法:

def make_class(method_name, method_body, s_value)
  klass = Class.new
  klass.class_eval "def #{method_name} ; #{method_body} ; end"
  klass.class_eval "def to_s ; #{s_value} ; end"
  klass
end

用法:

>> Anonymous = make_class(:foobar, "puts 'foo'", 23)
=> Anonymous
>> a = Anonymous.new
=> 23
>> a.foobar
foo
=> nil
>> a.to_s
=> 23

编辑:好的,我在这里有点过于简单,这不能处理方法的args。

答案 3 :(得分:0)

我不建议这样做,但你可以......

def make_class(method_name, method_body, s_value)
  eval("
  class Anonymous
      def #{method_name}(args)
          #{method_body}(args)
      end

      def to_s
         return '#{s_value}'
      end
  end
  ")
end

make_class(:bla, :puts, 'bla')
Anonymous.new.bla('moin')
puts Anonymous.new.to_s

返回

moin
bla