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」が未定義であるということです。私はメタプログラミングとルビーにかなり慣れていません、そしてこれは私を夢中にさせています。

4

3 に答える 3

2

私はあなたがそれをすべて間違っていると思います:)

メソッドを初めて呼び出すと、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_eval、クラスを呼び出す必要があります。Adder
  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 に答える