Mixins和/ Traits的一些好例子是什么?

时间:2008-12-10 10:32:04

标签: ruby language-agnostic mixins traits

我正在阅读Ruby,并了解了它的mixins模式,但是没想到很多有用的mixin功能(因为我不习惯这么想的方式)。所以我想知道什么是有用的Mixin功能的好例子?

由于

编辑:一点背景知识。我来自C ++和其他对象语言,但我怀疑的是Ruby说它不是继承mixins,但我一直认为mixins是多重继承,所以我担心我想把它们分类太快进入我的舒适区,并没有真正了解混合物是什么。

4 个答案:

答案 0 :(得分:12)

它们通常用于向类中添加某种形式的标准功能,而无需重新定义它们。您可能会认为它们有点像Java中的接口,但不是仅仅定义需要实现的方法列表,而是通过包含模块来实现 实现

标准库中有一些例子:

Singleton - 可以混合到任何类中以使其成为单例的模块。 initialize方法是私有的,并添加了一个实例方法,确保应用程序中只有该类的一个实例。

可比较 - 如果将此模块包含在类中,则定义< =>方法,它将当前实例与另一个对象进行比较,并说哪个更大,足以提供<,<,==,> =,>,以及?方法

可枚举 - 通过混合使用此模块并定义每个方法,您可以获得对所有其他相关方法的支持,例如collect,inject,select和reject。如果它也得到< =>方法,然后它也将支持sort,min和max。

DataMapper也是一个有趣的例子,可以使用简单的include语句,采用标准类,并添加将其持久保存到数据存储的功能。

答案 1 :(得分:9)

我认为通常的例子是持久性

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"

想象一下,这个模块是由一个Ruby忍者编写的,它会将你的类的状态保存到一个文件中。
现在假设我写了一个全新的类,我可以通过说include ModuleILike来混合它来重用持久性功能。您甚至可以在运行时包含模块。我只需将其混合即可免费加载并保存方法。这些方法就像您为自己的课程编写的方法一样。代码/行为/功能 - 没有继承的重用!

所以你正在做的是为你的类包含方法表的方法(不是字面上正确但接近)。

答案 2 :(得分:3)

在ruby中,Mixins不是多重继承的原因是mixin方法的组合是一次性的。这不会是一个大问题,除了Ruby的模块和类可以修改。这意味着如果您将模块混合到您的类中,然后向模块添加方法,则将不会对您的类可用;如果你以相反的顺序这样做,它就会。

这就像点一个冰淇淋蛋筒。如果你把巧克力粉和太妃糖作为你的混合物,然后带着你的锥体走开,如果有人在冰淇淋店里把巧克力洒在垃圾桶上,会有什么样的冰淇淋甜点不会改变。你的课程,冰淇淋甜筒,当mixin模块,洒水箱是。下一个使用该mixin模块的人将看到更改。

当您在ruby中include模块时,它会在该模块上调用Module#append_features,该模块会将该模块方法的副本一次性添加到包含器中。

据我所知,多重继承更像是委托。如果你的班级不知道如何做某事,它会问其父母。在开放类环境中,类的父级可能在创建类之后被修改。

这就像是RL亲子关系。你的母亲在你出生后可能已经学会了如何玩杂耍,但是如果有人要你玩杂耍,你要求她:告诉你如何(在你需要的时候复制它)或者为你做(纯粹的代表团),然后她即使你是在她的兼顾能力之前创造的,也能够做到这一点。

您可以通过修改Module#append_features以保留包含者列表,然后使用method_added回调更新它们来修改ruby模块“include”以更像多重继承,但是这将是标准Ruby的重大转变,并且在与其他代码合作时可能会导致重大问题。您可能最好创建一个名为Module#inherit的{​​{1}}方法并处理委派。

至于一个真实世界的例子,include很棒。如果在类中定义Enumerable并包含#each,则可以访问整个迭代器主机,而无需对每个迭代器进行编码。

答案 3 :(得分:1)

它主要用于在C ++中使用多重继承或在Java / C#中实现接口。我不确定你的经历在哪里,但如果你以前做过这些事,那么mixins就是你在Ruby中做的事情。这是一种将功能注入类的系统化方法。

寻找你感兴趣的贴纸↓↓↓
豫ICP备18024241号-1