module_function和extend self
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只影响其后定义的方法,或带参数时其前定义的方法