Tuesday, December 15, 2009

Inheritance pattern: contract via constructor

In C# and the C-ish object oriented languages, if you want a family of types to implement a property, with each implementation particularized to each type (i.e., you care that everyone implements it, but you don't want one implementation cascaded to all), the big two techniques get lots of press: object inheritance from an abstract base and interface implementation. Here's another technique that's unsurprising when you think about it, but I've never seen it discussed as such: I'll call it contract via constructor. It's a little more stringent than the two classic approaches, since a subclass can't dodge the contract (in C#, at compile time, anyway) by implementing the required property as
throw new NotImplementedException();
And, it's feasible for a non-abstract class.

The idea is for a base class to require a value via its constructor(s) rather than requiring it via abstract property. Obviously, this is not universally advisable. But I find I have at least one rather substantial object hierarcy in most apps: say, one for persistable objects, maybe another for DTOs, and if a UI is involved, often several flavors of controls or containers, plus architectural base types if we're doing MVVM or such. Often, there's something I'd like to code out once, in a base class, with slight variations for each leaf. There's usually a generic type parameter or two that expresses the type-specific variations, but sometimes there's additional metadata, staticly known to each leaf but not knowable in the general case up at the base. It's the sort of thing where a VB programmer would write an enum into the base class and ride to putative glory on a switch statement. Not so great for framework programming or for, really, any code that shouldn't make you want to fire someone.

In the few hours since I really noticed this and have been salting it around my current project before deciding to blog it, contract via constructor is particularly useful if the property you seek is metadata about each subtype, e.g., so that you can handle it universally in the base type.

For example, suppose I want to specialize IntBindingPair into a family of types, each associated with an IEntity<int>. (An IEntity<int> here is a persistable object with an int primary key, and a string property suitable for display. The "binding pair", therefore, is basically a key/value pair for UI binding.) My base class's constructor takes an int and a string. I want each new subtype to be constructable from just the IEntity reference, so I need each subtype to specify how to choose its string value. (No, it's not time to override ToString(). Go sit in the corner.)

I could use an abstract property:

public abstract Func<TEntity, string> ValueExtractor { get; }

But I'd still be stuck on how to map my child class's sole IEntity argument to my base class's int and string; the instance property isn't available to be used in constructor args, for obvious reasons.

So, when in need, inject a fix! (This is a more commendable motto in software design than in, say, intravenous drug use.)


public abstract class IntBindingPair<TEntity> : IntBindingPair
  where TEntity : class, IEntity<int>
{
  protected IntBindingPair(TEntity entity, Func<TEntity, string> valueExtractor)
    : base(entity.PrimaryKey1, valueExtractor.Invoke(entity))
  {
    ValueExtractor = valueExtractor;
  }

  public Func<TEntity, string> ValueExtractor { get; private set; }
}


Now any child type must provide a real (or at least non-null) value for ValueExtractor; otherwise it won't even instantiate.

public class FooDisplay : IntBindingPair<IFoo>
{
  public FooDisplay(IFoo foo)
    : base(foo, f => f.Bar)
  {}
}
public interface IFoo : IEntity<int>
{
  string Bar { get; }
}


This same syntax solves another, possibly more general problem: how to transform constructor signatures from child types to suit the requirements of a base type.

No comments: