Having a target class overriding a mixin's method is easy to implement – just use the OverrideMixin
attribute. In the following code sample, the programmer is impatient with the OnThePhoneMixin
's Wait
method and writes his own for the Parrot
class. This overriding Wait
slashes the milliseconds in half:
[Uses (typeof(OnThePhoneMixin))] public class Parrot { public virtual void Whistle () { Console.WriteLine ("'River Kwai march' here..."); } public virtual void Say (string s) { Console.WriteLine ("\"{0}\"", s); } // The 'Wait' method is part of the 'IOnThePhone' interface, // implemented by the 'OnThePhone' class, which brings its own // 'Wait' implementation. We override that method here. The // 'OnThePhone's 'Wait' method must be virtual for this to // work [OverrideMixin] public virtual void Wait (int milliseconds) { Console.WriteLine ("[The parrot's (overridden) method]"); Thread.Sleep (milliseconds / 2); } } |
|
The sophistication of the OverrideMixin
attribute lies not so much in the how, but in the when and why.
OverrideMixin
attributeNote that in the example above we have attributed the target class with Uses
instead of the mixin class with Extends
. As pointed out on the wiki-page re-motion mixins basics -- the 'Uses' attribute and the 'ObjectFactory'#Using {{Uses}}, this is the rare case. In practice, the Extends
attribute for attributing the mixin class is far more popular.
This situation is reversed for target classes overriding mixin methods, because the presence of the OverrideMixin
attribute nullifies the assumption that target classes shall be independent of what is mixed to them. Think about it: If the mixin class already knows it is supposed to extend a particular target class (and therefore attributed with Extends
), then it would probably be cleaner to subclass the mixin class, override the method in that subclass and use the subclass for mixing. So when is it useful to use Uses
and OverrideMixin
?
This question is not easy to answer. The next section on this page explains how to use OverrideMixin
productively for the template method pattern.
The template method pattern is useful for adding a "plan" or "procedural knowledge" to a target class. The wikipedia article on the subject gives the example of a simple engine for board games. The Chess
and Monopoly
specializations provide the methods for
The superordinate "template", the abstraction of how to conduct such a board game, is encoded in the base class.
If you look at our Parrot
class (hierarchy) and the OnThePhoneMixin
you will see something very similar:
Parrot
class knows how to say a given stringOnThePhoneMixin
class with its PretendToTalkOnThePhone
method is the plan and the procedure of what to say when to give the audience the illusion that the speaker is having a phone conversationThe author believes that putting the "template", the "plan" or "procedure" into an extra mixin class is a much cleaner way of implementing the template method pattern than the route of implementation inheritance given in the wikipedia article, because it is more flexible.
For this scheme to work, the target class must be able to override methods from the mixin implementing the template. Specializations might require to modify some (or even all) methods, but other specializations might be served well by the defaults provided by the template. In the contrived parrot example from the beginning of this page, the specialization was that the template's Wait
method waited for too long, for example.