2012-04-19 49 views
0

好的,所以這讓我瘋狂。這段代碼的意義在於,我應該能夠動態添加一個方法,只要它的形式爲object.plusnum,其中num是任意數字。我不太清楚如何讓這個工作。這是迄今爲止我的最佳投籃機會,但是我目前收到了一些錯誤。Ruby中的元編程錯誤

代碼:

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」 是不確定的。我對元編程和紅寶石很新,而這讓我瘋狂。

回答

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 
0
  1. 你必須調用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 

,然後逐步取代開始硬配線值可配置值,而不是一次寫入所有內容。

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(方法)來調用方法,否則它將返回nil來創建方法。或者你可以簡單的返回,返回@start_value +#{}號