I'm faced with a design decision that doesn't smell to me, but gives me pause. Take a look at the following code sample:
public interface IGenerator
{
///<summary>
/// Combines two generators; performs magic as well
/// </summary>
BaseGenerator Combine(BaseGenerator next);
///<summary>
/// Does what a generator does.
/// </summary>
object GenerateLolKThx();
}
public abstract class BaseGenerator : IGenerator
{
///<summary>
/// Combines two generators; performs magic as well
/// </summary>
public BaseGenerator Combine(BaseGenerator next)
{
// do stuff that I really don't want implementors to try and do
// because its complex and can result in bad juju if done wrong
return SuperSecretCombine(this, next);
}
///<summary>
/// Does what a generator does.
/// </summary>
public abstract object GenerateLolKThx();
/* other base class methods */
}
I don't want to go into more detail about WHY I don't want to trust implementors with the Combine method; suffice it to say its complex. I do, however, want to do my best to force anybody who wants to implement IGenerator to extend BaseGenerator, as that's the only way to properly combine two generators. This is enforced by the interface itself.
I'm worried that there are unexpected issues (indicated by a "smell") caused by my referencing an implementation of an interface within that interface. But I also know that this sort of thing isn't unheard of in CS, nor is it in and of itself bad (i.e., an XML schema that describes XSDs and language compilers that are written in the language they compile).
I'm interested in reasons WHY this might be a code smell, possible pitfalls caused by this type of design, and alternative designs that accomplish what I desire (ensure my implementation of Combine is used to combine any and all types of generators). TIA.