問題描述
我試圖理解 Mixin 的概念,但我似乎無法理解它是什么.我認(rèn)為它是一種通過使用繼承來擴(kuò)展類功能的方法.我讀過人們將它們稱為抽象子類".誰能解釋一下為什么?
I'm trying to get my head around the Mixin concept but I can't seem to understand what it is. The way I see it is that it's a way to expand the capabilities of a class by using inheritance. I've read that people refer to them as "abstract subclasses". Can anyone explain why?
如果您能根據(jù)以下示例(來自我的演講幻燈片之一)解釋您的答案,我將不勝感激:
I'd appreciate if you'd explain your answer based on the following example (From one of my lecture slideshows):
推薦答案
在討論混入是什么之前,描述它試圖解決的問題很有用.假設(shè)您有一堆想法或概念要建模.它們可能以某種方式相關(guān),但它們?cè)诖蠖鄶?shù)情況下是正交的——這意味著它們可以相互獨(dú)立.現(xiàn)在,您可以通過繼承對(duì)此進(jìn)行建模,并使每個(gè)概念都派生自某個(gè)通用接口類.然后在實(shí)現(xiàn)該接口的派生類中提供具體方法.
Before going into what a mix-in is, it's useful to describe the problems it's trying to solve. Say you have a bunch of ideas or concepts you are trying to model. They may be related in some way but they are orthogonal for the most part -- meaning they can stand by themselves independently of each other. Now you might model this through inheritance and have each of those concepts derive from some common interface class. Then you provide concrete methods in the derived class that implements that interface.
這種方法的問題在于,這種設(shè)計(jì)沒有提供任何清晰直觀的方法來獲取每個(gè)具體類并將它們組合在一起.
The problem with this approach is that this design does not offer any clear intuitive way to take each of those concrete classes and combine them together.
mix-ins 的想法是提供一堆原始類,其中每個(gè)類都為一個(gè)基本的正交概念建模,并且能夠?qū)⑺鼈冋吃谝黄鹨越M成更復(fù)雜的類,僅具有您想要的功能 - 有點(diǎn)像樂高積木.原始類本身旨在用作構(gòu)建塊.這是可擴(kuò)展的,因?yàn)樯院竽梢詫⑵渌碱愄砑拥郊现校粫?huì)影響現(xiàn)有的類.
The idea with mix-ins is to provide a bunch of primitive classes, where each of them models a basic orthogonal concept, and be able to stick them together to compose more complex classes with just the functionality you want -- sort of like legos. The primitive classes themselves are meant to be used as building blocks. This is extensible since later on you can add other primitive classes to the collection without affecting the existing ones.
回到 C++,這樣做的一種技術(shù)是使用模板和繼承.這里的基本思想是通過模板參數(shù)將這些構(gòu)建塊連接在一起.然后你將它們鏈接在一起,例如.通過 typedef
,形成一個(gè)包含你想要的功能的新類型.
Getting back to C++, a technique for doing this is using templates and inheritance. The basic idea here is you connect these building blocks together by providing them via the template parameter. You then chain them together, eg. via typedef
, to form a new type containing the functionality you want.
以您的示例為例,假設(shè)我們要在頂部添加重做功能.下面是它的樣子:
Taking your example, let say we want to add a redo functionality on top. Here's how it might look like:
#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() << '
'; // 84
mynum.undo();
cout << mynum.get() << '
'; // 42
mynum.redo();
cout << mynum.get() << '
'; // back to 84
}
你會(huì)注意到我對(duì)你的原作做了一些改動(dòng):
You'll notice I made a few changes from your original:
- 虛函數(shù)在這里真的不是必需的,因?yàn)槲覀冊(cè)诰幾g時(shí)確切地知道我們組合的類類型是什么.
- 我為第二個(gè)模板參數(shù)添加了一個(gè)默認(rèn)的
value_type
以使其使用不那么麻煩.這樣您就不必每次將一個(gè)片段粘在一起時(shí)都繼續(xù)輸入
. - 使用一個(gè)簡(jiǎn)單的
typedef
而不是創(chuàng)建一個(gè)從片段繼承的新類.
- The virtual functions really aren't necessary here because we know exactly what our composed class type is at compile-time.
- I've added a default
value_type
for the second template param to make its usage less cumbersome. This way you don't have to keep typing<foobar, int>
everytime you stick a piece together. - Instead of creating a new class that inherits from the pieces, a simple
typedef
is used.
請(qǐng)注意,這只是一個(gè)簡(jiǎn)單的例子來說明混入的想法.所以它沒有考慮極端情況和有趣的用法.例如,在沒有設(shè)置數(shù)字的情況下執(zhí)行 undo
可能不會(huì)像您預(yù)期的那樣工作.
Note that this is meant to be a simple example to illustrate the mix-in idea. So it doesn't take into account corner cases and funny usages. For example, performing an undo
without ever setting a number probably won't behave as you might expect.
作為旁注,您可能還會(huì)找到這篇文章 很有幫助.
As a sidenote, you might also find this article helpful.
這篇關(guān)于什么是 Mixin(作為一個(gè)概念)的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!