如何在Ruby中在运行时向现有对象实例添加方法?

时间:2011-11-12 13:41:53

标签: ruby metaprogramming

在Javascript中,我可以做到这一点。

var a = {};
a.f1 = function(){};

我如何在Ruby中执行此操作?


更新

在JS代码中,a是一个没有类实例化的对象。 function(){}是一个匿名函数,a.f1 =将函数添加到对象实例。因此,该函数仅绑定到实例,并且没有任何内容与类或类似定义相关。

2 个答案:

答案 0 :(得分:13)

Ruby和JS的对象模型非常不同,但直接翻译可能如下所示:

a = Object.new
def a.f1(x) 
  2*x
end

a.f1(5) #=> 10

您还可以使用Ruby的本征类:

class Object
  def metaclass
    class << self; self; end
  end
end

a = Object.new    
# Also: (class << a; self; end).send(:define_method, :f1) do |x|
a.metaclass.send(:define_method, :f1) { |x| 2*x }

警告说明:你会在元编程/ monkeypatching / ......中看到这种代码,但在编写&#34; normal&#34;时,这种代码并不常见。代码,其他技术(主要是模块混合)适用。

答案 1 :(得分:3)

JavaScript和其他语言之间存在差异,因为JavaScript以另一种方式进行继承。所以这里不能直接模拟。

让我们假装{}是红宝石中的A类,并从中创建对象

class A
end

a = A.new

并且某些模块B中的f1功能座位

module B
  def f1
    puts "you've extended your object"
  end
end

现在你可以用类似的方式做你想做的事了

a.extend(B)

a.f1 #=> "you've extended your object"