What Is C++ Mixin-Style

What are Mixins (as a concept)

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.

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.

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.

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.

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() << '\n'; // 84
mynum.undo();
cout << mynum.get() << '\n'; // 42
mynum.redo();
cout << mynum.get() << '\n'; // back to 84
}

You'll notice I made a few changes from your original:

  • 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.

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.

As a sidenote, you might also find this article helpful.

How do people get mixin-style re-use in C#?

In C#, the closest you get to C++ style mixins is adding the mixins as fields of a class and add a bunch of forwarding methods to the class:

public class MyClass
{
private readonly Mixin1 mixin1 = new Mixin1();
private readonly Mixin2 mixin2 = new Mixin2();

public int Property1
{
get { return this.mixin1.Property1; }
set { this.mixin1.Property1 = value; }
}

public void Do1()
{
this.mixin2.Do2();
}
}

This is usually enough, if you only want to import functionality & state of the mixins. A mixin can of course be implemented as you like, complete with (private) fields, properties, methods, etc.

If your class also needs to express "is-a" relationships with the mixins then you need to do the following:

interface IMixin1
{
int Property1 { get; set; }
}

interface IMixin2
{
void Do2();
}

class MyClass : IMixin1, IMixin2
{
// implementation same as before
}

(This is also the standard way how multiple inheritance is emulated in C#.)

Of course, the mixin interfaces as well as the mixin classes can be generics, e.g. with a most-derived class parameter or whatever.

What is a mixin and why is it useful?

A mixin is a special kind of multiple inheritance. There are two main situations where mixins are used:

  1. You want to provide a lot of optional features for a class.
  2. You want to use one particular feature in a lot of different classes.

For an example of number one, consider werkzeug's request and response system. I can make a plain old request object by saying:

from werkzeug import BaseRequest

class Request(BaseRequest):
pass

If I want to add accept header support, I would make that

from werkzeug import BaseRequest, AcceptMixin

class Request(AcceptMixin, BaseRequest):
pass

If I wanted to make a request object that supports accept headers, etags, authentication, and user agent support, I could do this:

from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin

class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
pass

The difference is subtle, but in the above examples, the mixin classes weren't made to stand on their own. In more traditional multiple inheritance, the AuthenticationMixin (for example) would probably be something more like Authenticator. That is, the class would probably be designed to stand on its own.

Mixins and .net

I'm no expert, but this is what I found.

  1. Mixins in C# 3.0
  2. Implementing Mixins with C# Extension Methods

From MSDN Blog:

Mixins In C#

Some suggest that extension methods in
the upcoming C# 3.0 are a kind of
Mixins, because you can put in
functionalities in these methods and
arbitrarily tag it onto any class you
want. In the C# 2.0 specification
section 20.1.3 it is clearly called
out that the base class of a generic
class has to be a constructed class
type so this rules out using the above
approach to be used in C#. I am not
too sure on why we choose to
explicitly disallow abstract subclass.
Since C# does not support
multiple-inheritance, IMO it should
have supported Mixin style coding.

What is the difference between a variable and a mixin in sass?

From the sass documentation

Variables begin with dollar signs, and are set like CSS properties.
You can then refer to them in properties:

$width: 5em;

#main {
width: $width; // width is set as 5em
}

On the other hand, Mixins allow you to define styles that can be re-used throughout the stylesheet

@mixin large-text { // defining mixing
font: {
family: Arial;
size: 20px;
weight: bold;
}
color: #ff0000;
}

.page-title { // applying mixin
@include large-text;
padding: 4px;
margin-top: 10px;
}

The above code is compiled to:

.page-title {
font-family: Arial;
font-size: 20px;
font-weight: bold;
color: #ff0000;
padding: 4px;
margin-top: 10px; }

scss mixin for custom css properties

You need to interpolate the $cssProperty variable (so it becomes #{$cssProperty}, just like you have done with the $side variable. So your final code should be:

@mixin genericSidesStyles ($sides, $style, $cssProperty) {
@if($sides == '') {
#{$cssProperty}: $style;
}
@else {
@each $cssProperty, $side in $sides {
@if ($side == 'top' or $side == 'bottom' or $side == 'left' or $side == 'right' ) {
#{$cssProperty}-#{$side}: $style;
}
}
}
}


Related Topics



Leave a reply



Submit