Ruby:这两种混合模块方法的方法是等价的吗?

yvfmudvl  于 2023-01-30  发布在  Ruby
关注(0)|答案(1)|浏览(104)

我有一个模块和一门课。

module Dog
  def speak
    "woof"
  end
end

class Daschund; end

我创建了类的两个单独示例。

sausage = Daschund.new
saveloy = Daschund.new

如果我想添加Dog#woof作为我的两个新对象的示例方法,我可以用两种方法来完成:
一个一个二个一个一个一个三个一个一个一个一个一个一个四个一个一个一个一个一个五个一个
这两个方法是等价的吗?我知道第一个方法将模块的方法添加到对象的元类中。object#extend做同样的事情吗?或者它做的事情稍微不同?有什么方法可以证明这一点吗?

3qpi33ja

3qpi33ja1#

根据Object的文档,用模块扩展对象意味着将该模块包含到对象的单例类中:
extend:包含self的单例类中的给定模块。
检查两个对象的单例类的ancestors可以确认这一点:

sausage.singleton_class.ancestors
#=> [#<Class:#<Daschund:0x00007fa6af92e868>>, Dog, Daschund, Object, Kernel, BasicObject]

saveloy.singleton_class.ancestors
#=> [#<Class:#<Daschund:0x00007fa6af92e778>>, Dog, Daschund, Object, Kernel, BasicObject]

实际的实现细节当然取决于Ruby的实现和版本,对于MRI/YARV,rb_extend_object定义为:

void
rb_extend_object(VALUE obj, VALUE module)
{
    rb_include_module(rb_singleton_class(obj), module);
}

相关问题