2016-05-30 89 views
2

我正在阅读'Metaprogramming Ruby',并同时编写一些代码以阐明概念。我已经读过,当你多次包含/预先安装一个模块时,所有进一步的包含都不会改变祖先链中所述模块的位置。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]。显然这没有发生。

一旦儿子包括父亲,它开始在父模块中查找并找到include Grandfatherprepend GratGrandfather。它实际上'进入'Grandfather它包括GreatGrandfather,只有然后执行prepend GreatGrandfather线(并忽略它,因为它已经存在于血统)?

真相被告知,我怀疑我会从中得到多少用处,但不会因为知道模块彼此“链”的确切程度而受到伤害。

@edit - 我多花了一些时间,而且在任何情况下,我的直觉似乎都没有错。我已经包含了我认为可以实现的两种方式的图片,一种是指令后的指令,另一种是关于创建继承层次的图片 - 看起来发生在图片中的那种方式与给出的原始示例背道而驰,所以#1或#2都不能正在发生。

修改的示例代码(仅曾祖父改变)

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 

enter image description here

在总结 - 我仍然不知道是怎么回事了

回答

1

Module#prepend_feature

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.You着修改例子是这样的:

module GreatGrandfather 
    include Grandfather 
end 

module Grandfather 
    include GreatGrandfather 
end 

因为当你定义曾祖父的祖父没有定义的。

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 
+0

谢谢您的回答,虽然说实话它并不十分清楚。我已经添加了一些更多的信息信息 - 你可以称重吗? – blob

+0

呵呵,我实际上只是自己弄明白了,因为我完全忽略了模块中的代码立即执行。我一直在玩它,所以我错过了它抱怨单一化常量 - 如果我把它放在一个文件中,这个问题从一开始就会有明确的答案。谢谢! – blob