Mixins are a language idea similar to multiple inheritance, but rather than extending a class a mixin works by defining an interface plus various functionality associated with that interface. It avoids the pathologies of multiple inheritance and is a flexible way of providing add-on functionality.
In C# we can create a mixin with a combination of an interface plus extension methods. LINQ is the canonical example of this with two core interfaces IEnumerable<T> and IQueriable<T> and a collection of extension methods on those interfaces.
It's easy to create your own mixins. For example, say I want to provide location functionality to various entities. I can define an interface like this:
public interface ILocatable { int Longitude { get; set; } int Latitude { get; set; } }
And then some extension methods for that interface:
public static class LocatableExtensions { public static void MoveNorth(this ILocatable locatable, int degrees) { // ... } public static void MoveWest(this ILocatable locatable, int degrees) { // .. } }
Now, if we've got some entities like:
public class Ship : ILocatable { public int Longitude { get; set; } public int Latitude { get; set; } } public class Car : ILocatable { public int Longitude { get; set; } public int Latitude { get; set; } }
We can use the mixin like this:
Ship ship = new Ship(); ship.MoveNorth(10); Car car = new Car(); car.MoveWest(23);
It's a very nice pattern for adding capabilities to entities.
I am no 100% sure myself of the "true" definition of a mixin but one has to consider that the fact that it's not possible to either create instance variables (for both class and interface extension) or access protected members in an extension method (for a class extension) makes things difficult to truly extend such types ?
ReplyDeleteHi Daniel,
ReplyDeleteYou are right, it's a limited form of extensibility compared to inheritance, but then it's more flexible in it's application; a single class can have many different mixins applied to it. you can only have one base class. In a way mixins better support the open-closed principle by allowing an addition of functionality (by adding extension methods of the interface) without any change to existing code.
It's true you can't access protected members or add new fields, but because a mixin is based around an interface you have that interface to tell you what you need to know about the class being mixed-into.
I think it's important not to see mixins as somehow replacing inheritance. They are just another design pattern you can use to help you factor your code.
This is not a mixin.. it's not even a trait. You still ended up implementing everything required in the interface, and you still need to put a "using ... " statement at the top of every file which you're using extension methods in.
ReplyDelete@Anon: You've need the relevant Using tag at the top anyway to access the interface ... just put the extension methods in a public static class in the same namespace as the interface.
ReplyDelete*You'd
ReplyDelete