We can make Chevy Chase' New Shimmer skit even more funny by adding a shaving cream to the mix, giving our civilization a shaving dessert wax:
And, as already mentioned in re-motion mixins basics -- the 'Extends' attribute, it does not end there: our application can mixin super glue, vitamins – even extra calcium! The problem is that you have to cast to an interface for the members of each mixin class. This leads to excessive typing.
Enter the finger-friendly attribute
CompleteInterface. You combine the interfaces for all mixins and an interface for the target class with multiple inheritance and attribute that super interface with
Then you pass that interface to the
ObjectFactory; out comes and instance that sports all members from all mixin classes and the target class natively – no casts required.
For brevity, we will demonstrate the
CompleteInterface attribute for the components implementing
IDessertTopping(we introduce an interface for the target class here),
IFloorWaxMixin(already introduced in previous sections)
In practice, you can combine as many interfaces as you need.
Now you can tell the
ObjectFactory that a new interface,
IShavingDessertWax combines all the interfaces required for a shaving dessert wax instance, and that this interface and the implementations for its various components together implement the extended
DessertTopping target class:
This measure comes with two benefits:
- it makes casting to interfaces obsolete when using various mixed in members in the instance
- it makes instantiation completely abstract, because we pass an interface to
ObjectFactory, not a class
The client code is clean and compact:
CompleteInterface for inversion of control?
Decoupling an interface from its implementation is an extremely useful strategy for keeping code maintainable and among the first things aspiring software architects learn. So-called inversion-of-control containers store the knowledge of which implementation should map to which interface, the factory reads in this mapping and returns instances to the application based on this mapping. This design pattern is unrelated to mixins, because it is much broader in scope.
You might feel tempted to use re-motion mixin and its
CompleteInterface for this task, because it gives you a way of mapping between implementation classes and interfaces for free. This, however, is not recommended, for the following reasons:
- dedicated IOC libraries exist, and they are much more appropriate for decoupling interfaces and implementations
- you can't decouple in such a fashion that it actually makes sense – you would have to modify the interface's source code with the
CompleteInterfaceattribute every time you change the mapping
In other words: use something like the castle project's for inversion of control Windsor Container, not the re-motion mixin library.
Find the sample code for this exercise in subversion.