66

プログラミングの演習として、クラスを作成し、そのクラスから 2 つのオブジェクトをインスタンス化し、1 つのオブジェクトにモンキーパッチを適用し、method_missing を使用してもう 1 つのオブジェクトにモンキーパッチを適用する Ruby スニペットを作成しました。

これが取引です。これは意図したとおりに機能します。

class Monkey

  def chatter
    puts "I am a chattering monkey!"
  end

  def method_missing(m)
    puts "No #{m}, so I'll make one..."
    def screech
      puts "This is the new screech."
    end
  end
end

m1 = Monkey.new
m2 = Monkey.new

m1.chatter
m2.chatter

def m1.screech
  puts "Aaaaaargh!"
end

m1.screech
m2.screech
m2.screech
m1.screech
m2.screech

method_missing のパラメーターがあることに気付くでしょう。これを行ったのは、define_method を使用して不足しているメソッドを適切な名前で動的に作成することを望んでいたためです。しかし、うまくいきません。実際、define_method を静的な名前で使用しても、次のようになります。

def method_missing(m)
  puts "No #{m}, so I'll make one..."
  define_method(:screech) do
    puts "This is the new screech."
  end
end

次の結果で終了します。

ArgumentError: wrong number of arguments (2 for 1)

method method_missing   in untitled document at line 9
method method_missing   in untitled document at line 9
at top level    in untitled document at line 26
Program exited.

エラー メッセージをより当惑させているのは、引数が 1 つしかないことですmethod_missing

4

3 に答える 3

140

define_methodオブジェクトClassの (プライベート) メソッドです。インスタンスから呼び出しています。というインスタンス メソッドがないdefine_methodためmethod_missing、今度は:define_method(不足しているメソッドの名前) と:screech(に渡した唯一の引数) を使用して、 に再帰しますdefine_method

代わりにこれを試してください (すべての Monkey オブジェクトで新しいメソッドを定義するため):

def method_missing(m)
    puts "No #{m}, so I'll make one..."
    self.class.send(:define_method, :screech) do
      puts "This is the new screech."
    end
end

またはこれ(オブジェクトの「固有クラス」を使用して、呼び出されたオブジェクトでのみ定義する場合):

def method_missing(m)
    puts "No #{m}, so I'll make one..."
    class << self
      define_method(:screech) do
        puts "This is the new screech."
      end
    end
end
于 2008-10-09T04:58:17.037 に答える
4
def method_missing(m)
    self.class.class_exec do
       define_method(:screech) {puts "This is the new screech."}
    end 
end

screech メソッドは、すべての Monkey オブジェクトで使用できます。

于 2010-08-27T04:46:01.967 に答える
4

self.class.define_method(:screech) は機能しません。define_method はプライベート メソッドであるためです。

class << self
    public :define_method
end
def method_missing(m)
puts "No #{m}, so I'll make one..."
Monkey.define_method(:screech) do
  puts "This is the new screech."
end
于 2008-10-28T02:56:20.513 に答える