【问题标题】:Creating methods with class_eval使用 class_eval 创建方法
【发布时间】:2013-01-20 15:35:23
【问题描述】:

我想写一个方法,它接受一个参数并创建另一个方法,用这个参数命名。这是我的代码

class Class
  def createMethod(attr_name)
    attr_name = attr_name.to_s
    class_eval %Q{
        def #{attr_name}
            puts "bar"
        end
    }
  end
end

p Class.new.createMethod("foo").respond_to?(:foo)

不幸的是,respond_to?(:foo) 的计算结果为 false。怎么了?

【问题讨论】:

    标签: ruby methods metaprogramming class-eval


    【解决方案1】:

    这是因为class_eval 是一个类方法,并且您在实例的上下文中调用它。你可以这样做:

    class Class
      def createMethod(attr_name)
        attr_name = attr_name.to_s
        self.class.class_eval %Q{
            def #{attr_name}
                puts "bar"
            end
        }
        self # Return yourself if you want to allow chaining methods
      end
    end
    

    这是irb 执行此操作时的输出:

    irb(main):001:0> class Class
    irb(main):002:1>   def createMethod(attr_name)
    irb(main):003:2>     attr_name = attr_name.to_s
    irb(main):004:2>     self.class.class_eval %Q{
    irb(main):005:2"         def #{attr_name}
    irb(main):006:2"             puts "bar"
    irb(main):007:2"         end
    irb(main):008:2"     }
    irb(main):009:2>   end
    irb(main):010:1> end
    => nil
    irb(main):011:0> clazz = Class.new
    => #<Class:0x007fd86495cd58>
    irb(main):012:0> clazz.respond_to?(:foo)
    => false
    irb(main):013:0> clazz.createMethod("foo")
    => nil
    irb(main):014:0> clazz.respond_to?(:foo)
    => true
    

    【讨论】:

    • 它仍然为假的原因是您的createMethod 调用返回nil,而不是实例,因此您不能链接respond_to? 调用。您可以将self 放在createMethodend 之前,这样就可以了。
    • 不要发布文本图像,而是将实际文本直接复制并粘贴到您的帖子中。文本图像不易解析、搜索或访问。
    • @AndrewMarshall 会的。固定。
    猜你喜欢
    • 2012-03-22
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    相关资源
    最近更新 更多