module Persistence
def load sFileName
puts "load code to read #{sFileName} contents into my_data"
end
def save sFileName
puts "Uber code to persist #{@my_data} to #{sFileName}"
end
end
class BrandNewClass
include Persistence
attr :my_data
def data=(someData)
@my_data = someData
end
end
b = BrandNewClass.new
b.data = "My pwd"
b.save "MyFile.secret"
b.load "MyFile.secret"
4条答案
按热度按时间332nm8kg1#
它们通常用于向类添加某种形式的标准功能,而无需重新定义所有功能。您可能会认为它们有点像Java中的接口,但不仅仅是定义需要实现的方法列表,其中许多方法实际上将通过包含模块来实现。
标准库中有几个例子:
Singleton -一个可以混合到任何类中使其成为单例的模块。initialize方法是私有的,并添加了一个示例方法,这确保在应用程序中只有该类的一个示例。
Comparable -如果你在一个类中包含这个模块,定义<=>方法,它将当前示例与另一个对象进行比较,并指出哪个更大,就足以提供<,<=,==,>=,>和之间?方法。
通过混合这个模块,并定义一个each方法,你可以获得对所有其他相关方法的支持,如collect,inject,select和reject。如果它也有<=>方法,那么它也将支持sort,min和max。
DataMapper也是一个有趣的例子,说明了使用简单的include语句可以完成什么,获取一个标准类,并添加将其持久化到数据存储的能力。
3okqufwl2#
我认为最常见的例子是持久性
字符串
假设模块是由Ruby忍者编写的,它将类的状态持久化到文件中。
现在假设我写了一个全新的类,我可以通过混合
include ModuleILike
来重用持久化的功能。你甚至可以在运行时包含模块。我可以通过混合来免费获得load和保存方法。这些方法就像你自己为你的类编写的方法一样。代码/行为/功能-重用而不继承!所以你所做的就是将方法包含到你的类的方法表中(不是字面上正确的,但很接近)。
xnifntxz3#
在ruby中,mixin不是多重继承的原因是组合mixin方法是一次性的。这不是一个大问题,除了Ruby的模块和类是开放的修改。这意味着如果你mixin一个模块到你的类,然后添加一个方法到模块,方法 * 将不会 * 对你的类可用;如果你以相反的顺序执行,它会。
这就像订购一个冰淇淋蛋筒。如果你得到巧克力屑和太妃糖屑作为你的混合物,然后带着你的蛋筒离开,那么即使有人在冰淇淋店的巧克力屑箱里添加了五颜六色的巧克力屑,你得到的冰淇淋蛋筒的种类也不会改变。你的类,冰淇淋蛋筒,在混合模块,下一个使用mixin模块的人将看到这些变化。
当你在ruby中
include
一个模块时,它会在这个模块上调用Module#append_features
,它会一次性将这个模块的方法的副本添加到includer中。多重继承,据我所知,更像是委托。如果你的类不知道如何做某事,它会询问它的父母。在开放类环境中,类的父母可能在类创建后被修改。
这就像RL亲子关系。你的母亲可能在你出生后就学会了如何变戏法,但如果有人让你变戏法,你让她做:告诉你怎么做(在你需要的时候复制)或为你做(纯粹的委托),那么她就能做到,即使你在她变戏法的能力出现之前就被创造出来了。
你可以修改ruby模块“include”,使其更像多重继承,方法是修改
Module#append_features
以保留一个包含器列表,然后使用method_added
回调函数更新它们,但这与标准Ruby相比是一个很大的转变,并且在处理其他代码时可能会导致重大问题。您可能会更好地创建一个调用include
并处理委托的Module#inherit
方法。作为一个真实的例子,
Enumerable
非常棒。如果你定义了#each
并在你的类中包含Enumerable
,那么你就可以访问一大堆迭代器,而不必对每一个迭代器都进行编码。rxztt3cl4#
mixin的用法主要是在C++中使用多重继承,或者在Java/C#中实现接口。我不知道你的经验如何,但如果你以前做过这些事情,mixin就是你在Ruby中做这些事情的方式。