C++ Mixins, A Powerful Concept

I just came across a very interesting concept, and imo, quite powerful. Unfortunately, I currently only knows that it works on C++ using my VS2008. I find it even more amazing that this concept stems from ice cream toppings, that is according to wikipedia and some other coherent sources.

One customer enters the ice cream palor, selects a chocolate ice cream as the base, and then adds oreo toppings to create his own oreo-chocolate ice cream. Another customer comes along and chooses the same chocolate ice cream base, but this time adds cherry and chips to create his cheery-chips-chocolate ice cream. This concept was first coined as Mix-ins.

Similarly, in programming, the objective is to allow the programmer to select a base class and then add functional features to it, the way toppings are added to ice cream. Quite amazingly, the resultant code looks exactly as described in words: base ice cream wrapped around with toppings. We’ll see how this is possible.

Suppose today we want to create a Man with a Mouth. Traditionally, OOP makes you create a 2 classes: a Man and a Mouth, and then put the Mouth in the Man.

public class Mouth {
public:
        void Talk() { Console::WriteLine("Hello World"); }
};

public class Man {
public:
       Mouth mouth; // OOP: the Man has a Mouth
};

int main()
{
        Man peter;
        peter.Talk(); // real traditional OOP.
        return 0;
}

All neat and nice. And we’ve got a reusable Mouth that we can use in a Woman class for example. We also have a reusable Man class, but if and only if the new Man also has got a Mouth.

Suppose now I want to create a Man that also has the functionality of Legs, we cannot really create Legs and add them inside Man directly, unless we alter the source which breaks the reusability. The traditional solution is to create a WalkingMan that inherits Man. So there you have it:

public class WalkingMan : Man
{
public:
        void Walk() { Console::WriteLine("I'm walking on sunshine"); };
}

int main()
{
        WalkingMan peter;
        peter.Talk(); // real traditional OOP.
        peter.Walk(); // now my man can walk too!
        return 0;
}

Although the above solution works, it poses a critical problem: every time we want a Man with new abilities, we have to write a new Man class with that ability. And the vicious cycle continues because the new class may not have other abilities that another programer wants. For example, you cannot create a SkippingWalkingMan from a WalkingMan and a SkippingMan. The former is true even if multiple inheritance is possible.

Enter mixins, or in our local ice cream lingo, toppings. To turn our class library into an ice cream parlor, we first need to create a some base flavors:

public class Chocolate {

};
public class Vallina {

};

Now we create the mixins or toppings. This is where is cleverness comes in:

template<class T>
public class Oreo : public T {
public:
        void LickOreo() { Console::WriteLine("Orea is great"); }
};
template<class T>
public class Chips : public T {
public:
        void LickChips() { Console::WriteLine("Chips is crunchy"); }
};
template<class T>
public class Cherry : public T {
public:
        void LickCherry() { Console::WriteLine("Cheery is Juicy"); }
};

finally in our program, we can create any ice cream we want by literally wrapping our ice cream with mixins (or toppings)!

int main()
{
        Oreo<Chocolate> OreaChocolateIceCream;
        Cherry<Chips<Chocolate>> CherryChipsChocolateIceCream;
        Oreo<Chips<Cherry>Vallina>>> OreoChipsCherryVallinaIceCream;
        // all so yummy!
        return 0;
}

The templated class is called a Mixin class, and they provide a powerful way to create modular functionality that can be reused over and over again. As a creator of a Mixin library, you can create new ability classes without worrying about the base, thus allowing very high code portability.

There’s one caveat though. If 2 Mixins have functions of the same name, the outter most Mixin will override. If all the Mixins had Lick(), you would be Lick()ing the outter most Mixin! But this can be avoided by prefixing function names with the class name. Simple!

2 thoughts on “C++ Mixins, A Powerful Concept

  1. David

    I don’t care that I’m 3 years late to the party, thank you for this clear example of mixins. I abhor the examples that are super convoluted and confusing.

    Reply
  2. LJ

    Similarly late to the game, but this is a really nice clear explanation.

    While you can’t achieve the same conciseness as with templates, you can achieve nearly the same modularity and reuse using traditional C++ OOP techniques separating interface (pure abstract class) and implementation. Example code below. It’s somewhat tedious, and it would be nice if C++ had better syntactic support for interfaces and implementations.

    #include

    using namespace std;

    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    // Interfaces
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

    class Chocolate {
    public:
    };

    class Vanilla {
    public:
    };

    class Oreo
    {
    public:
    virtual void LickOreo() const = 0;
    };

    class Chips
    {
    public:
    virtual void LickChips() const = 0;
    };

    class Cherry
    {
    public:
    virtual void LickCherry() const = 0;
    };

    class OreoChocolate : public Oreo, public Chocolate
    {
    public:
    static OreoChocolate *New();
    };

    class CherryChipsChocolate : public Cherry, public Chips, public Chocolate
    {
    public:
    static CherryChipsChocolate *New();
    };

    class OreoChipsCherryVanilla : public Oreo, public Chips, public Cherry, public Vanilla
    {
    public:
    static OreoChipsCherryVanilla *New();
    };

    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    // Implementations
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

    class VanillaImpl : public Vanilla
    {
    public:
    };

    class ChocolateImpl : public Chocolate {
    public:
    };

    class OreoImpl : public Oreo
    {
    public:
    virtual void LickOreo() const { cout << "Oreos are great!" << endl; }
    };

    class ChipsImpl : public Chips
    {
    public:
    virtual void LickChips() const { cout << "Chips are crunchy!" << endl; }
    };

    class CherryImpl : public Cherry
    {
    public:
    virtual void LickCherry() const { cout << "Cherries are juicy!" << endl; }
    };

    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    // Aggregate implementations
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

    class OreoChocolateImpl : public OreoChocolate, public OreoImpl, public ChocolateImpl
    {
    public:
    void LickOreo() const { return OreoImpl::LickOreo(); }
    };

    class CherryChipsChocolateImpl : public CherryChipsChocolate, public CherryImpl, public ChipsImpl, public ChocolateImpl
    {
    public:
    void LickCherry() const { return CherryImpl::LickCherry(); }
    void LickChips() const { return ChipsImpl::LickChips(); }
    };

    class OreoChipsCherryVanillaImpl : public OreoChipsCherryVanilla, public OreoImpl, public ChipsImpl, public CherryImpl, public VanillaImpl
    {
    public:
    void LickOreo() const { return OreoImpl::LickOreo(); }
    void LickChips() const { return ChipsImpl::LickChips(); }
    void LickCherry() const { return CherryImpl::LickCherry(); }
    };

    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    // Interface static member implementations
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

    OreoChocolate *
    OreoChocolate::New()
    {
    return new OreoChocolateImpl;
    }

    CherryChipsChocolate *
    CherryChipsChocolate::New()
    {
    return new CherryChipsChocolateImpl;
    }

    OreoChipsCherryVanilla *
    OreoChipsCherryVanilla::New()
    {
    return new OreoChipsCherryVanillaImpl;
    }

    /////////////////////////////////////////////////////////

    int
    main(int argc, char *argv[])
    {
    OreoChocolate *oreoChocolate = OreoChocolate::New();
    CherryChipsChocolate *cherryChipsChocolate = CherryChipsChocolate::New();
    OreoChipsCherryVanilla *oreoChipsCherryVanilla = OreoChipsCherryVanilla::New();

    cout << "I think:" <LickOreo();
    oreoChipsCherryVanilla->LickChips();
    oreoChipsCherryVanilla->LickCherry();
    }

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>