# 示例代码01 moduleSkill defself.included(base) base.extend(ClassMethod) base.class_eval do deffly puts 'I can fly' end end end moduleClassMethod defrun puts 'Everybody can run' end end end
# 源代码01 # Define class methods from given block. # You can define private class methods as well. # .... defclass_methods(&class_methods_module_definition) mod = const_defined?(:ClassMethods, false) ? const_get(:ClassMethods) : const_set(:ClassMethods, Module.new)
mod.module_eval(&class_methods_module_definition) end
# 源码02 # Evaluate given block in context of base class, # so that you can write class macros here. # When you define more than one +included+ block, it raises an exception. defincluded(base = nil, &block) if base.nil? if instance_variable_defined?(:@_included_block) if@_included_block.source_location != block.source_location raiseMultipleIncludedBlocks end else @_included_block = block end else super end end
module A defself.included(target) v = target.instance_methods.include?(:method_name) puts "in included: #{v}" end
defself.append_features(target) v = target.instance_methods.include?(:method_name) puts "in append features before: #{v}" super v = target.instance_methods.include?(:method_name) puts "in append features after: #{v}" end
defmethod_name end end
class X include A end
# 以上代码的输出为 # in append features before: false # in append features after: true # in included: true
没错,append_features 的方法是先于 included 执行的回调方法,可以在引入模块的前后进行基本的变量设置等操作
defappend_features(base) #:nodoc: if base.instance_variable_defined?(:@_dependencies) base.instance_variable_get(:@_dependencies) << self false else returnfalseif base < self @_dependencies.each { |dep| base.include(dep) } super base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods) base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block) end end