0

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

代码:

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_eval("def #{method} return @start_value + #{number} end")
        else
            super
        end
    else
        super
    end
end

end

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

4

3 回答 3

2

我认为你完全错了:)

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

您正在使用class_eval字符串并将其传递给它,这通常是个坏主意,出于安全和性能原因,应尽可能使用块。

我怎么看它可能看起来:

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
于 2012-04-19T08:54:18.717 回答
1
    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} 简单地返回

于 2012-04-19T08:11:04.187 回答
0
  1. 您必须调用类,而不是 adder 的实例class_evalAdder
  2. 该字符串不是有效的 Ruby。后面加上括号#{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

然后逐渐用可配置的值代替硬连线的值,而不是一次写所有东西。

于 2012-04-19T08:00:02.787 回答