繁体   English   中英

Ruby - 多次包含单个模块和祖先层次结构

[英]Ruby - including single module multiple times and ancestry hierarchy

我现在正在阅读“元编程 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 前面加上祖先树,并且祖先树将设置为[Son, GreatGrandfather, Father, Grandfather] 显然这并没有发生。

一旦 Son 包含了Father,它就会开始在Father 模块中查找并找到include Grandfather并在prepend GratGrandfather 其实是否“进入” Grandfather那里包括曾祖父,然后才执行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

在此处输入图片说明

总而言之 - 我仍然不知道它是如何发生的

模块#prepend_feature

如果此模块尚未添加到 mod 或其祖先之一,Ruby 的默认实现是将此模块的常量、方法和模块变量覆盖到 mod。

但是您已经通过祖父将曾祖父添加到父亲。

这样它就会像你期望的那样工作:

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.This is, 当你将模块添加到另一个模块时会发生什么。 注释说明了模块层次结构在时间上会发生什么:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM