我正在阅读'Metaprogramming Ruby',同时编写一些代码来澄清概念。我已经读过,当您多次包含/添加单个模块时,所有进一步的包含都不会改变所述模块在祖先链中的位置。
我编写了一些代码,这些代码以我没想到的方式工作 - 那里实际发生了什么?
module GreatGrandfather; end
module Grandfather
include GreatGrandfather
end
module Father
include Grandfather
prepend GreatGrandfather
end
module Son
include Father
end
Son.ancestors # => [Son, Father, Grandfather, GreatGrandfather]
我假设当我跑Son.ancestors
时,儿子将包括父亲,父亲将包括祖父并且在前祖父和祖先树将被设置为[Son, GreatGrandfather, Father, Grandfather]
。显然这没有发生。
一旦Son包含父亲,它就会开始查看父模块并找到include Grandfather
和prepend GratGrandfather
。它是否真的'进入'Grandfather
它包含GreatGrandfather,然后只执行prepend GreatGrandfather
行(并忽略它,因为它已经存在于祖先中)?
说实话,我怀疑我会从中获得多少用处,但知道模块之间的链条是如何完全没有关系的。
@edit - 我已经玩了很多,而且似乎我的直觉在任何一种情况下都不对。我已经包含了一张我认为可以采用的两种方式的图片,一个接一个的指令,一个关于创建继承层次结构的图片 - 图片中出现的一个图片与给出的原始示例相反,所以#1或#2都不能正在发生。
修改后的示例代码(仅更改了GreatGrandfather)
module GreatGrandfather
include Grandfather
end
module Grandfather
include GreatGrandfather
end
module Father
prepend GreatGrandfather
include Grandfather
end
module Son
include Father
end
Son.ancestors # => Son, GreatGrandfather, Father, Grandfather
总结 - 我仍然不知道它是如何发生的
答案 0 :(得分:1)
Ruby的默认实现是覆盖常量,方法, 如果此模块没有,则将此模块的模块变量修改为mod 已被添加到mod或其祖先之一。
但是你已经通过祖父将GreatGrandfather添加到了父亲那里。
这样可以按预期工作:
module GreatGrandfather; end
module Grandfather
include GreatGrandfather
end
module Father
prepend GreatGrandfather
include Grandfather
end
module Son
include Father
end
p Son.ancestors # => [Son, GreatGrandfather, Father, Grandfather]
<强>更新强>
1.你不能修改这样的例子:
module GreatGrandfather
include Grandfather
end
module Grandfather
include GreatGrandfather
end
因为你定义了GreatGrandfather Grandfather没有定义。
2.这就是将模块添加到其他模块时会发生什么。注释说明了模块层次结构及时发生的情况:
module GreatGrandfather
# GG
end
module Grandfather
# GG
# G
include GreatGrandfather
# GG
# G -> GG
end
module Father
# GG
# G -> GG
# F
prepend GreatGrandfather
# GG
# G -> GG
# GG -> F
include Grandfather
# Don't change the position of GG in Father hierarchy, cause it is already in ancestors
# GG
# G -> GG
# GG -> F -> G
end
module Son
# GG
# G -> GG
# GG -> F -> G
# S
include Father
# GG
# G -> GG
# GG -> F -> G
# S -> GG -> F -> G
end