延伸红宝石物体; extend_object回调可防止实例方法被扩展

2 ruby module object extend

在使用模块扩展对象实例时遇到一些麻烦,特别是当我在Module类中定义extend_object回调时.我的理解是,当你做类似的事情:

(s = String.new).extend SomeModule

调用SomeModule extend_object回调.这似乎是这种情况,但是当我包含一个回调时,SomeModule中定义的实例方法都不会在对象中可见.有些代码应该更好地解释一下:

module M1
  def self.extend_object(o)
  end

  def test_method
    true
  end
end

module M2
  def test_method
    true
  end
end

(x = String.new).extend(M1)
(y = String.new).extend(M2)
Run Code Online (Sandbox Code Playgroud)

然后,

x.methods.include?("test_method")
=> false
y.methods.include?("test_method")
=> true
Run Code Online (Sandbox Code Playgroud)

进一步来说,

x.singleton_methods
=> []
y.singleton_methods
=> ["test_method"]
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

参考:

http://www.ruby-doc.org/core/classes/Module.html#M001660
http://www.ruby-doc.org/core/classes/Object.html#M000337
Run Code Online (Sandbox Code Playgroud)

tom*_*fro 10

您应该使用extended回调而不是覆盖extend_object.第一个是在模块扩展对象时调用的.调用后者实际扩展对象.这就像之间的差异includedappend_features.

这是一个例子:

module M1
  def self.extended(base)
    puts "extended object #{base.inspect}"
  end

  def test_method
    true
  end
end
Run Code Online (Sandbox Code Playgroud)

然后:

>> (x = String.new).extend(M1)
extended object ""
=> ""

>> x.methods.include?("test_method")
=> true
Run Code Online (Sandbox Code Playgroud)