当前位置:  开发笔记 > 后端 > 正文

Ruby:define_method vs. def

如何解决《Ruby:define_methodvs.def》经验,为你挑选了1个好方法。

作为一个编程练习,我编写了一个Ruby片段,它创建了一个类,从该类中实例化了两个对象,monkeypatches一个对象,并依赖于method_missing来monkeypatch另一个.

这是交易.这按预期工作:

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...



1> Avdi..:

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


作为一般规则,这说明为什么你应该总是a)在`method_missing`中使用白名单,这样你*只*处理你实际上*感兴趣的那些方法,并且b)转发你所做的一切*不*想要使用`super`处理"食物链".
@JörgWMittag我可能会在线上有更多的单词*b)使用super来转发你不想处理的"食物链".?*
推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有