Ruby中的元编程错误

Ruby中的元编程错误,ruby,metaprogramming,Ruby,Metaprogramming,好吧,这让我发疯了。这段代码的要点是,我应该能够动态添加一个方法,只要它的形式是object.plusnum,其中num是任意数字。我不太清楚如何让它工作。这是我迄今为止最好的一次尝试,但我目前遇到了几个错误 代码: 我目前遇到的错误是“class_eval”未定义。我对元编程和ruby相当陌生,这让我发疯 您必须在Adder类上调用class\u eval,而不是在Adder实例上调用 该字符串无效。在#{method}后面加括号 新版本的代码: class Adder def initial

好吧,这让我发疯了。这段代码的要点是,我应该能够动态添加一个方法,只要它的形式是object.plusnum,其中num是任意数字。我不太清楚如何让它工作。这是我迄今为止最好的一次尝试,但我目前遇到了几个错误

代码:

我目前遇到的错误是“class_eval”未定义。我对元编程和ruby相当陌生,这让我发疯

  • 您必须在
    Adder
    类上调用
    class\u eval
    ,而不是在Adder实例上调用
  • 该字符串无效。在
    #{method}
    后面加括号
  • 新版本的代码:

    class Adder
    def initialize(_val)
        @start_value = _val
    end
    
    def method_missing(method_name, *args)
        method = method_name.to_s
        if method.start_with?("plus") then
            num = method[4 .. method.length]
            if (/^[\d]+(\.[\d]+){0,1}$/ === num) then
                number = Integer(num)
                self.class.class_eval("def #{method}() return @start_value + #{number} end")
            else
                super
            end
        else
            super
        end
    end
    
    end
    
    a = Adder.new(0)
    a.plus1
    
    就我自己而言,我建立这种方法的方法只是从

    class Adder
    end
    
    Adder.class_eval("def plus1() return 0 + 1 end")
    a = Adder.new
    a.plus1
    
    然后逐渐用可配置的值替换硬连接的值,而不是一次写入所有内容

        class Adder
    def initialize(_val)
        @start_value = _val
    end
    
    def method_missing(method_name, *args)
        method = method_name.to_s
        if method.start_with?("plus") then
            num = method[4 .. method.length]
            if (/^[\d]+(\.[\d]+){0,1}$/ === num) then
                number = Integer(num)
                self.class.class_eval("def #{method}() return @start_value + #{number} end")
                eval(method)
            else
                super
            end
        else
            super
        end
    end
    
    end
    
    a = Adder.new(0)
    a.plus1
    
  • 您必须在
    Adder
    类上调用
    class\u eval
    ,而不是在Adder实例上调用
  • 该字符串无效。在
    #{method}
    后面加括号
  • 新版本的代码:

    class Adder
    def initialize(_val)
        @start_value = _val
    end
    
    def method_missing(method_name, *args)
        method = method_name.to_s
        if method.start_with?("plus") then
            num = method[4 .. method.length]
            if (/^[\d]+(\.[\d]+){0,1}$/ === num) then
                number = Integer(num)
                self.class.class_eval("def #{method}() return @start_value + #{number} end")
            else
                super
            end
        else
            super
        end
    end
    
    end
    
    a = Adder.new(0)
    a.plus1
    
    就我自己而言,我建立这种方法的方法只是从

    class Adder
    end
    
    Adder.class_eval("def plus1() return 0 + 1 end")
    a = Adder.new
    a.plus1
    
    然后逐渐用可配置的值替换硬连接的值,而不是一次写入所有内容

        class Adder
    def initialize(_val)
        @start_value = _val
    end
    
    def method_missing(method_name, *args)
        method = method_name.to_s
        if method.start_with?("plus") then
            num = method[4 .. method.length]
            if (/^[\d]+(\.[\d]+){0,1}$/ === num) then
                number = Integer(num)
                self.class.class_eval("def #{method}() return @start_value + #{number} end")
                eval(method)
            else
                super
            end
        else
            super
        end
    end
    
    end
    
    a = Adder.new(0)
    a.plus1
    
    确保在最后添加eval(method)以调用该方法,否则仅创建该方法时它将返回nil。或者您可以使用return@start_value+#{number}简单返回


    确保在最后添加eval(method)以调用该方法,否则仅创建该方法时它将返回nil。或者您可以使用return@start_value+#{number}简单地返回

    第一次调用一个方法会产生与第二次调用不同的结果,因此您可能希望在定义后立即调用该方法。另外--您正在使用相当复杂的正则表达式,然后将值转换为
    整数
    ,并删除点后面的所有数字

    您正在使用
    class\u eval
    并向其传递字符串,这通常是个坏主意,出于安全和性能原因,应该尽可能使用block

    我怎么看呢

    class Adder
      def initialize(val)
        @start_value = val
      end
    
      def method_missing(method_name, *args)
        if method_name.to_s =~ /^plus(\d+)$/
          self.class.class_eval do
            define_method(method_name) { @start_value + $1.to_i }
          end
          self.send(method_name)
        else
          super
        end
      end
    end
    

    我想你全搞错了:)

    第一次调用一个方法会产生与第二次调用不同的结果,因此您可能希望在定义后立即调用该方法。另外--您正在使用相当复杂的正则表达式,然后将值转换为
    整数
    ,并删除点后面的所有数字

    您正在使用
    class\u eval
    并向其传递字符串,这通常是个坏主意,出于安全和性能原因,应该尽可能使用block

    我怎么看呢

    class Adder
      def initialize(val)
        @start_value = val
      end
    
      def method_missing(method_name, *args)
        if method_name.to_s =~ /^plus(\d+)$/
          self.class.class_eval do
            define_method(method_name) { @start_value + $1.to_i }
          end
          self.send(method_name)
        else
          super
        end
      end
    end