extend self是在单例类父类链中加入当前module。如果改变以后删除或重定义,会影响类方法(其实一般都用这个,很少见module_function)

module E
  extend self
  def e
    1
  end
end

o = String.new
o.extend E

puts E.singleton_class.ancestors.join ', '
puts o.singleton_class.ancestors.join ', '

=> #, E, Module, Object, Kernel, BasicObject
=> #<class:#>, E, String, Comparable, Object, Kernel, BasicObject</class:#</class:e></code></pre>


而Module functions are copies of the original and so may be changed independently. The instance-method versions are made private. If used with no arguments, subsequently defined methods become module functions

其实现大概如下:

class Module
  def my_module_function *methods
    if methods.empty?
      class << self
        def method_added name
          private name
          singleton_class.send :define_method, name, instance_method(name)
        end
      end
    else
      methods.each do |name|
        private name
        singleton_class.send :define_method, name, instance_method(name)
      end
    end
  end
end


若想做到changed independently,需带参数(方法名)使用,这样,当重定义该方法时,因已用define_method指向旧方法体,所以不影响类方法

其private特性可带来以下好处:

The biggest advantage of module_function methods is that when their encompassing module gets included into a class the methods do not become public method of that class – which is a good thing, as they don’t extend the class’s public API (and don’t need to be kept backward-compatible)

此外,module一旦调用extend self,所有方法都会成为类方法,因为每次调用类方法时都重新查找继承链。而module_function只影响其后定义的方法,或带参数时其前定义的方法