Mixin 和/或 Traits 有哪些很好的例子?

问题描述 投票:0回答:4

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

谢谢

编辑:一些背景知识。我来自 C++ 和其他对象语言,但我的疑问是 Ruby 说它不会继承 mixins,但我一直将 mixins 视为多重继承,所以我担心我太快地将它们分类到我的舒适区,并没有真正理解 mixin 是什么。

ruby language-agnostic mixins traits
4个回答
13
投票

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

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

Comparable - 如果您将此模块包含在类中,则定义

方法(将当前实例与另一个对象进行比较并确定哪个更大)是否足以提供

=、> 和 Between?方法。<=> <, <=, ==, >Enumerable - 通过混合此模块并定义

each

方法,您可以获得对所有其他相关方法(例如收集、注入、选择和拒绝)的支持。如果它也有 方法,那么它也将支持排序、最小值和最大值。 <=>DataMapper 也是一个有趣的示例,展示了可以使用简单的 include 语句、采用标准类并添加将其持久保存到数据存储的功能来完成的操作。


11
投票

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 ninja 编写的,它将类的状态保存到文件中。
现在假设我编写一个全新的类,我可以通过说

include ModuleILike
混合它来重用持久性功能。您甚至可以在运行时包含模块。我只需将其混合即可免费获得加载和保存方法。这些方法就像您自己为班级编写的方法一样。代码/行为/功能-无需继承即可重用!

因此,您正在做的是将方法包含到您的类的方法表中(不是字面上正确,但很接近)。


3
投票
不会

对您的类可用;如果你按照相反的顺序做,它就会。 这就像点一个蛋卷冰淇淋。如果你得到巧克力糖粉和太妃糖碎片作为你的混合物,然后带着你的甜筒走开,即使有人在冰淇淋店的巧克力糖粉箱中添加五彩糖粉,你所拥有的冰淇淋类型也不会改变。你的类(冰淇淋甜筒)没有被修改,而 mixin 模块(洒水箱)却被修改了。下一个使用该 mixin 模块的人将会看到这些变化。

当您在 ruby 中

include

某个模块时,它会在该模块上调用

Module#append_features
,这会将该模块的方法的副本一次添加到包含器中。

多重继承,据我理解,更像是委托。如果你的班级不知道该怎么做,就会询问家长。在开放类环境中,类的父级可能在类创建后已被修改。

这就像RL亲子关系。你出生后,你的母亲可能已经学会了如何杂耍,但如果有人要求你杂耍,而你要求她要么:向你展示如何(当你需要时复制)或为你做(纯粹委托),那么她到那时就能够了,即使你是在她具备杂耍能力之前被创造出来的。

您可以通过修改

Module#append_features

来保留包含器列表,然后使用

method_added
回调更新它们,从而修改 ruby 模块“include”,使其更像多重继承,但这将是一个很大的转变来自标准 Ruby,并且在与其他代码一起使用时可能会导致重大问题。您可能最好创建一个调用
Module#inherit
并处理委托的
include
方法。

对于现实世界的例子,

Enumerable

非常棒。如果您定义

#each
并在您的类中包含
Enumerable
,那么您就可以访问一整套迭代器,而无需对每个迭代器进行编码。
    


1
投票

© www.soinside.com 2019 - 2024. All rights reserved.