2012-04-19 6 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メソッド" は未定義であるということです。私はmetaprogrammingとrubyにかなり新しいです、そして、これは私を夢中にしています。

答えて

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. あなたはAdderクラスではなく、加算器のインスタンスにclass_evalを呼び出す必要があります。
  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 +#{番号}