The Ultimate Mixin

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
User avatar
cyboryxmen
Posts: 163
Joined: November 14th, 2014, 2:03 am

The Ultimate Mixin

Post by cyboryxmen » January 24th, 2018, 8:41 am

Mixins are great. They allow you to mix in different components together to make a single class. This gives the class an amazing amount of customisability as you can plug in different components to change its behaviour. It also allows the components to be more independent from each other allowing them to be reused for other classes.

The problem I had with them mostly have to do with encapsulation. To allow the different components to access each other's members, they must make them public exposing their interface.

With my implementation of mixins, the components can choose to make their members protected to allow them to be used only by other components in the mixin. Additionally, A component will still have the freedom to make their members private to to restrict them from everyone but the component itself.

Additionally, I gave the mixin a master component as the component that the mixin will inherit constructors for automating mixin construction. Automating construction was hard because a mixin can have so many components. To prevent the need to initialise them all, only one master component will need to be initialised. If the other components need values that must be initialised, it'll be in the master component. All variables by design should be only in the master component.

Here's a demonstration on how the class might be used:

Code: Select all

#include <iostream>
#include "Mixin.h"

template<typename Accessor>
class Template1
{
protected:
	void Func1 ( )
	{
		std::cout << "Func1 called!\n";
		static_cast< Accessor* >( this )->Func2 ( );
	}
};
template<typename Accessor>
class Template2
{
protected:
	void Func2 ( )
	{
		std::cout << "Func2 called!\n";
		static_cast< Accessor* >( this )->Func3 ( );
	}
};
template<typename Accessor>
class Template3
{
protected:
	void Func3 ( )
	{
		std::cout << "Func3 called!\n";
		static_cast< Accessor* >( this )->FinalFunc ( );
	}
};
template<typename Accessor>
class MasterTemplate
{
public:
	MasterTemplate ( const int num ) : num_ { num }
	{

	}

	void MasterFunc ( )
	{
		std::cout << "Func chain start!\n";
		static_cast< Accessor* >( this )->Func1 ( );
	}

protected:
	void FinalFunc ( )
	{
		std::cout << "Success! Here's your number: " << num_ << "\n";
	}

private:
	int num_;
};

int main ( )
{
	using namespace template_bullshit;

	std::cout << "Enter a number: ";
	int input;
	std::cin >> input;

	Mixin <MasterTemplate, Template1, Template2, Template3> mixin { input };
	mixin.MasterFunc ( );

	system ( "pause" );
	return 0;
}
As you can see, the interface is pretty simple to use. Here's the repository. I hope that you found it as useful as I did.
Zekilk

Post Reply