新手问题 对 ActiveSupport::Concern 中 append_features 的疑问

monkeygq · 发布于 2017年02月25日 · 最后由 bajiudongfeng 回复于 2017年03月21日 · 512 次阅读
28316

结合《Ruby元编程》的例子写了如下代码,有几点疑问,感谢解答:

  1. 为什么Concern中的append_features会执行三次
  2. 链式包含问题如代码这样理解是否正确
module Concern
  def self.extended(base)
    p "extended:self=#{self},base=#{base}"
    base.instance_variable_set(:@_dependencies, []) 
  end 
  def append_features(base)
    if base.instance_variable_defined?(:@_dependencies)
      base.instance_variable_get(:@_dependencies) << self
      p "if:self=#{self},base=#{base},@=#{base.instance_variable_get(:@_dependencies)}"
      return false
    else
      return false if base < self
      p "else:self=#{self},@_dependencies=#{@_dependencies}"
      @_dependencies.each { |dep| base.include(dep) }
      super
      base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
    end 
  end 
end

module Myc2
  extend Concern
  def m3
    p "Myc2 instance method"
  end 
  module ClassMethods
    def m4
      p "Myc2 class method"
    end 
  end 
end

module Myc1
  extend Concern
  include Myc2
  def m1
    p "Myc1 instance method"
  end 
  module ClassMethods
    def m2
      p "Myc1 class method"
    end 
  end 
end

class Mytest
  include Myc1
end

输出如下:

"extended:self=Concern,base=Myc2"
"extended:self=Concern,base=Myc1"
"if:self=Myc2,base=Myc1,@=[Myc2]"
"else:self=Myc1,@_dependencies=[Myc2]"
"else:self=Myc2,@_dependencies=[]"
共收到 2 条回复
17727

为什么三次?

Myc1.include Myc2; Mytest.inlcude Myc1; Mytest.include Myc2;

理解是否正确?

哪里有什么理解?

14935

没有执行三次

class Mytest
  include Myc1
end
"else:self=Myc1,@_dependencies=[Myc2]"
"else:self=Myc2,@_dependencies=[]"

这个才是class包含的时候的结果。当include Myc1的时候调用Myc1的append_features的else部分。 此时self 是Myc1,base是Mytest.

@_dependencies.each { |dep| base.include(dep) }

这个是一个递归调用,相当于执行了Mytest.include(Myc2)
因此会调用Myc2的append_features
此时的self是Myc2,base是Mytest,所以继续走else部分
但是此时数组@_dependencies是空的
因此直接走下边的super,把Myc2放入Mytest的继承链中
直到Myc2的append_features运行结束
然后再回到Myc1的append_features中执行其super方法,把Myc1放入Mytest的继承链中。直到结束。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册