如何使用method_missing动态声明方法?

ben*_*nbs 5 ruby closures metaprogramming

我有一个ruby程序,我想接受用户的编写方法,并用该名称创建一个新方法.我试过这个:

def method_missing(meth,*args,&block)
  name = meth.to_s
  class << self
    define_method(name) do
      puts "hello " + name
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

`define_method': interning empty string (ArgumentError) in 'method_missing'
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?谢谢.

编辑:

我让它以不同的方式工作,但我仍然很好奇如何以这种方式做到这一点.这是我的代码:

def method_missing(meth,*args,&block)
  Adder.class_eval do
    define_method(meth) do
      puts "hello " + meth
    end
  end
  send("#{meth}")
end
Run Code Online (Sandbox Code Playgroud)

Chu*_*uck 12

该变量name在类定义(class << self)范围内不可用.它没有抛出NameError,因为你已经覆盖了method_missing.

要做你想做的事,你需要保持范围name.为了做到这一点,你必须只使用基于块的方法(例如class_eval)而不是直接打开类,所以像这样:

def method_missing(meth,*args,&block)
  name = meth.to_s
  eigenclass = class << self; self; end
  eigenclass.class_eval do
    define_method(name) do
      puts "hello " + name
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

但实际上,符号meth就足够了 - 你根本就不需要名字.(尽管你仍然需要上述技术.)最重要的是,你想立即执行该方法.最简单的方法就是重新发送消息:

def method_missing(meth,*args,&block)
  eigenclass = class << self; self; end
  eigenclass.class_eval do
    define_method(meth) do
      puts "hello #{meth}"
    end
  end
  send(meth, *args, &block)
end
Run Code Online (Sandbox Code Playgroud)

  • 而不是'eigenclass = class << self; 自; 结束`你可以简单地做 - "self.class.class_eval" (2认同)