我试图理解 Mixin 的概念,但我似乎无法理解它是什么。 我认为它是一种通过使用继承来扩展类功能的方法。 我读过人们将它们称为“抽象子类”。谁能解释一下为什么?
如果您能根据以下示例(来 self 的演讲幻灯片之一)解释您的答案,我将不胜感激:
最佳答案
在讨论什么是混合之前,先描述一下它试图解决的问题是很有用的。假设您有一堆要建模的想法或概念。它们可能以某种方式相关,但它们在很大程度上是正交的——这意味着它们可以彼此独立地独立存在。现在,您可以通过继承对此进行建模,并让这些概念中的每一个都派生自某个公共(public)接口(interface)类。然后在实现该接口(interface)的派生类中提供具体方法。
这种方法的问题在于,这种设计没有提供任何清晰直观的方法来获取每个具体类并将它们组合在一起。
mix-ins 的想法是提供一堆原始类,其中每个类都模拟一个基本的正交概念,并且能够将它们粘在一起以组成具有您想要的功能的更复杂的类——有点像像乐高积木。原始类本身旨在用作构建 block 。这是可扩展的,因为稍后您可以将其他原始类添加到集合中,而不会影响现有的。
回到 C++,实现这一点的一种技术是使用模板和继承。这里的基本思想是通过模板参数将这些构建 block 连接在一起。然后,您将它们链接在一起,例如。通过typedef
, 形成一个包含你想要的功能的新类型。
以您的示例为例,假设我们要在顶部添加重做功能。下面是它的样子:
#include <iostream>
using namespace std;
struct Number
{
typedef int value_type;
int n;
void set(int v) { n = v; }
int get() const { return n; }
};
template <typename BASE, typename T = typename BASE::value_type>
struct Undoable : public BASE
{
typedef T value_type;
T before;
void set(T v) { before = BASE::get(); BASE::set(v); }
void undo() { BASE::set(before); }
};
template <typename BASE, typename T = typename BASE::value_type>
struct Redoable : public BASE
{
typedef T value_type;
T after;
void set(T v) { after = v; BASE::set(v); }
void redo() { BASE::set(after); }
};
typedef Redoable< Undoable<Number> > ReUndoableNumber;
int main()
{
ReUndoableNumber mynum;
mynum.set(42); mynum.set(84);
cout << mynum.get() << '\n'; // 84
mynum.undo();
cout << mynum.get() << '\n'; // 42
mynum.redo();
cout << mynum.get() << '\n'; // back to 84
}
您会注意到我对您的原始版本做了一些更改:
- 这里实际上不需要虚函数,因为我们在编译时就知道我们的组合类类型是什么。
- 我添加了一个默认值
value_type
第二个模板参数使其使用不那么麻烦。这样您就不必继续输入<foobar, int>
每次你把一 block 拼在一起。 - 不是创建一个从片段继承的新类,而是一个简单的
typedef
已使用。
请注意,这是一个简单的示例来说明混入的想法。所以它没有考虑极端情况和有趣的用法。例如,执行 undo
如果不设置数字,可能不会像您预期的那样运行。
作为旁注,您可能还会发现 this article有帮助。
关于c++ - 什么是 Mixin(作为一个概念),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18773367/