Ruby中DefineMethod与def的比较?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (37)

作为编程练习,我编写了一个创建类的Ruby片段,实例化该类中的两个对象,monkeypatches一个对象,并依靠method_missing来对另一个对象进行monkeatch。

这按预期工作:

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.

比错误信息更令人困惑的是,我只有一个method_missing......

提问于
用户回答回答于

define_method是对象Class的(私有)方法。你正在从一个实例调用它。没有实例方法被调用define_method,所以它会返回给你method_missing,这次是:define_method(缺少方法的名称)和:screech

试试这个:

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
用户回答回答于

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

扫码关注云+社区