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

Eon*_*nil 3 ruby metaprogramming

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

var a = {};
a.f1 = function(){};
Run Code Online (Sandbox Code Playgroud)

我怎么能用Ruby做到这一点?


更新.

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

tok*_*and 13

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

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

a.f1(5) #=> 10
Run Code Online (Sandbox Code Playgroud)

您还可以使用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 }
Run Code Online (Sandbox Code Playgroud)

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

  • @Edmund,但是这会添加方法:bar到类的所有实例,我理解OP想要只将它添加到特定的实例. (2认同)

meg*_*gas 5

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

假设 {} 是 ruby​​ 中的 A 类,您可以从中创建对象

class A
end

a = A.new
Run Code Online (Sandbox Code Playgroud)

某些模块 B 中的 f1 功能席位

module B
  def f1
    puts "you've extended your object"
  end
end
Run Code Online (Sandbox Code Playgroud)

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

a.extend(B)

a.f1 #=> "you've extended your object"
Run Code Online (Sandbox Code Playgroud)