Tuesday, May 18, 2010

Inheritance and Constructors

Here's a common scenario: say you have a base class that does some work that relies on the setting of one of its properties. In the example I'll show, I have an abstract class designed to fill a DataSet from SQL, based on the TableName member of the class.
Each sub-class will set TableName, because each sub-class will be filling it's own table.

Our first attempt at creating these two classes looks like this:


public class BizObj
{
protected string TableName="default";
private DataSet oData;

public BizObj()
{
this.LoadData();
}
public void LoadData()
{
SqlConnection oConn = new SqlConnection("...");
SqlDataAdapter oAdapter = new SqlDataAdapter("SELECT * FROM " + this.TableName, oConn);
oAdapter.Fill(this.oData);
}
}
public class AuthorBizObj: BizObj
{
public AuthorBizObj()
{
this.TableName="Authors";
}
}

This does not work. Why? Because when instantiating any class, its base class constructor always fires first. My example used an abstract base class, but the same applies to a non-abstract class. So, in this example, the BizObj (base class) constructor fires before the AuthorBizObj (sub-class) constructor. By then, it's too late to set the TableName (which has already been set in the BizObj base class).

The trick to fixing this is to use a virtual Property, rather than a member, and to override that Property in each sub-class:

public class BizObj
{
protected virtual string TableName { get; set; }
private DataSet oData;

public BizObj()
{
this.LoadData();
}
public void LoadData()
{
SqlConnection oConn = new SqlConnection("...");
SqlDataAdapter oAdapter = new SqlDataAdapter("SELECT * FROM " + this.TableName, oConn);
oAdapter.Fill(this.oData);
}
}
public class AuthorBizObj: BizObj
{
protected override string TableName
{
get {return "Authors;}
}
public AuthorBizObj()
{
// whether or not you have this constructor
// does not affect the how the constructor fires
// I left a non-functional constructor in this example
// simply for illustrative purposes. You can leave it
// out if you have nothing to code in it.
}

}

So, there are two important points to take away from the above illustration:

1) When a class has been sub-classed, the base class constructor always runs before the sub-class constructor.

2) The member variables are instanced  in just the opposite order:  the base class member variables are set after the sub-class member variables (the above examples don’t quite illustrate this point). Keep in mind, I’m talking about member variables (which cannot be virtual and so cannot be overridden in a sub-class). My examples above used virtual properties (with getters/setters), which aren’t set until they’re accessed.