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

发布于 2024-07-11 04:42:24 字数 234 浏览 7 评论 0原文

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

谢谢

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

I was reading up on Ruby, and learned about its mixins pattern, but couldn't think of many useful mixin functionality (because I'm not used to thinking that way most likely). So I was wondering what would be good examples of useful Mixin functionality?

Thanks

Edit: A bit of background. I'm Coming from C++, and other Object languages, but my doubt here is that Ruby says it's not inheriting mixins, but I keep seeing mixins as Multiple inheritance, so I fear I'm trying to categorize them too soon into my comfort zone, and not really grok what a mixin is.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一身软味 2024-07-18 04:42:24

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

标准库中有一些示例:

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

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

可枚举 - 通过混合此模块并定义 each 方法,您可以获得对所有其他相关方法(例如收集、注入、选择和拒绝)的支持。 如果它也有 <=>; 方法,那么它还将支持排序、最小值和最大值。

DataMapper 也是一个有趣的示例,说明可以使用简单的 include 语句、采用标准类并添加将其持久保存到数据存储的功能来完成任务。

They are usually used to add some form of standard functionality to a class, without having to redefine it all. You can probably think of them a bit like interfaces in Java, but instead of just defining a list of methods that need to be implemented, many of them will actually be implemented by including the module.

There are a few examples in the standard library:

Singleton - A module that can be mixed into any class to make it a singleton. The initialize method is made private, and an instance method added, which ensures that there is only ever one instance of that class in your application.

Comparable - If you include this module in a class, defining the <=> method, which compares the current instance with another object and says which is greater, is enough to provide <, <=, ==, >=, >, and between? methods.

Enumerable - By mixing in this module, and defining an each method, you get support for all the other related methods such as collect, inject, select, and reject. If it's also got the <=> method, then it will also support sort, min, and max.

DataMapper is also an interesting example of what can be done with a simple include statement, taking a standard class, and adding the ability to persist it to a data store.

玩套路吗 2024-07-18 04:42:24

嗯,我认为常见的例子是持久化

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

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

Well the usual example I think is Persistence

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"

Imagine the module is written by a Ruby ninja, which persists the state of your class to a file.
Now suppose I write a brand new class, I can reuse the functionality of persistence by mixing it in by saying include ModuleILike. You can even include modules at runtime. I get load and save methods for free by just mixing it in. These methods are just like the ones that you wrote yourself for your class. Code/Behavior/Functionality-reuse without inheritance!

So what you're doing is including methods to the method table for your class (not literally correct but close).

执笔绘流年 2024-07-18 04:42:24

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

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

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

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

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

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

至于现实世界的例子,Enumerable 非常棒。 如果您在类中定义#each 并包含Enumerable,那么您就可以访问一整套迭代器,而无需对每个迭代器进行编码。

In ruby, the reason that Mixins aren't multiple-inheritance is that combining mixin methods is a one time thing. This wouldn't be such a big issue, except that Ruby's modules and classes are open to modification. This means that if you mixin a module to your class, then add a method to the module, the method will not be available to your class; where if you did it in the opposite order, it would.

It's like ordering an ice-cream cone. If you get chocolate sprinkles and toffee bits as your mixins, and walk away with your cone, what kind of ice cream cone you have won't change if someone adds multicolored sprinkles to the chocolate sprinkles bin back at the ice-cream shop. Your class, the ice cream cone, isn't modified when the mixin module, the bin of sprinkles is. The next person to use that mixin module will see the changes.

When you include a module in ruby, it calls Module#append_features on that module, which add a copy of that module's methods to the includer one time.

Multiple inheritance, as I understand it, is more like delegation. If your class doesn't know how to do something, it asks its parents. In an open-class environment, a class's parents may have been modified after the class was created.

It's like a RL parent-child relationship. Your mother might have learned how to juggle after you were born, but if someone asks you to juggle and you ask her to either: show you how (copy it when you need it) or do it for you (pure delegation), then she'll be able at that point, even though you were created before her ability to juggle was.

It's possible that you could modify a ruby module 'include' to act more like multiple inheritance by modifying Module#append_features to keep a list of includers, and then to update them using the method_added callback, but this would be a big shift from standard Ruby, and could cause major issues when working with others code. You might be better creating a Module#inherit method that called include and handled delegation as well.

As for a real world example, Enumerable is awesome. If you define #each and include Enumerable in your class, then that gives you access to a whole host of iterators, without you having to code each and every one.

想念有你 2024-07-18 04:42:24

它被广泛使用,因为人们可能在 C++ 中使用多重继承或在 Java/C# 中实现接口。 我不确定你的经验在哪里,但如果你以前做过这些事情,mixin 就是你在 Ruby 中做这些事情的方式。 它是一种将功能注入类的系统化方法。

It is largely used as one might use multiple inheritance in C++ or implementing interfaces in Java/C#. I'm not sure where your experience lies, but if you have done those things before, mixins are how you would do them in Ruby. It's a systemized way of injecting functionality into classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文