来自模块
Module#append_features(mod) → mod
当此模块包含在另一个模块中时,Ruby 会调用此模块中的append_features,并将其传递给mod 中的接收模块。 Ruby 的默认实现是 添加 将此模块的常量、方法和模块变量添加到 mod(如果该模块尚未添加到 mod 或其祖先之一)。
Module#prepend_features(mod) → mod
当这个模块被添加到另一个模块中时,Ruby 会调用 prepend_features 在这个模块中,将其传递给mod中的接收模块。 Ruby 的默认设置 实现是覆盖常量、方法和模块 如果该模块尚未被修改,则修改该模块的变量 添加到 mod 或其祖先之一。
谁能帮助我理解以下问题:
除了默认的功能外,
Module
还有哪些功能被定义为append
和prepend
?
它们在功能上有何不同?
何时使用
append_features
以及何时使用prepend_features
?
上面两条粗线有什么区别?
正如您引用的文本中所指定的:
常量、方法和模块变量
两者都将混合模块的方法添加到传递的模块(类)中。区别在于这些方法的查找顺序,如果目标类已经定义了它们:
include
的行为就好像目标类继承了混合模块:
module FooBar
def say
puts "2 - Module"
end
end
class Foo
include FooBar
def say
puts "1 - Implementing Class"
super
end
end
Foo.new.say # =>
# 1 - Implementing Class
# 2 - Module
prepend
使混合模块中的方法“更强”并首先执行它们:
module FooBar
def say
puts "2 - Module"
super
end
end
class Foo
prepend FooBar
def say
puts "1 - Implementing Class"
end
end
Foo.new.say # =>
# 2 - Module
# 1 - Implementing Class
这个例子是从这里抄来的:http://blog.crowdint.com/2012/11/05/3-killer-features-that-are-coming-on-ruby-2-0.html
当您想将目标模块(类)的方法保留在方法查找链的末尾时,请使用
prepend
。
通过搜索
ruby
、module
和 prepend
可以找到一些现实世界的示例:
(注意:我只提到方法,因为它们在继承和混合方面最容易想象,但这同样适用于其他功能。)
我想将其添加为@Mladen Jablanovic 已经做出的好答案的评论,但由于我的声誉较低,我不能这样做。
我在此处的帖子中找到了更简洁、更清晰和更具描述性的答案 - Ruby 模块:包含 vs Prepend vs Extend,我将其发布在这里,以防万一有人需要它并且可以轻松获得它。
直接引用:
虽然 include 是将外部代码导入到类中的最常见方法,但 Ruby 还提供了另外两种方法来实现这一点:extend 和 prepend。然而,它们根本没有相同的行为,并且这些差异经常被 Ruby 开发人员误解。
要了解如何使用它们,我们必须首先更深入地了解 Ruby 如何使用称为祖先链的东西来解析要在运行时执行的方法。
当创建 Ruby 类时,它会保存一个常量名称列表,这些常量名称是其祖先。它们是该类继承的所有类,以及它们包含的模块。例如,通过调用 String 类的祖先,我们可以获得其祖先的列表:
String.ancestors => [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]
include 是最常用且最简单的导入模块代码的方法。当在类定义中调用它时,Ruby 会将模块插入到类的祖先链中,就在其超类之后。
自 Ruby 2 起可用,对于 Ruby 爱好者来说,prepend 比它的另外两个朋友不太了解。它实际上像 include 一样工作,只不过不是将模块插入链中的类及其超类之间,而是将其插入到链的底部,甚至在类本身之前。
我建议阅读这篇文章以更好地理解它,因为它附带了示例。