Saturday, June 29, 2013

Inheritance and Constructors

I see frequent questions on the Forums where code doesn’t seem to work right and it comes down to the poster’s lack of understanding about the order in which the constructors are executed for the base class and a sub-class.

Here's a common scenario: say you have a base class that does some work (in the example I'll show, it is a generic class to fill a DataSet from SQL, based on the TableName property of the class). Each sub-class of this base class will provide it's own TableName property, because each sub-class will be filling it's own table.

The first attempt at creating these two classes, looks like this:

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

    public BizObj()
    {
        LoadData();
    }

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

    }
}

public class AuthorBizObj : BizObj
{
    public AuthorBizObj()
    {
        this.TableName = "Authors";
    }
}

However, this does not work. Why? Because the BizObj (base class) constructor fires before the AuthorBizObj (sub-class) constructor, not the other way around. And then it's too late to set the TableName at that point.

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
{
   public string m_TableName="";

   protected virtual string TableName
   {
      get {return this.m_TableName;}
      set {this.m_TableName = value;}
   }

   private DataSet oData;

   public BizObj()
   {
      LoadData();
   }

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

   }
}

public class AuthorBizObj : BizObj
{
    protected override string TableName
    {
        get { return "Authors"; }
    }
}

6 comments:

  1. How it been work if including and UI (form)?
    Thanks

    ReplyDelete
    Replies
    1. I don't think that I understand your question ... do you mean a sub-class of a Form instead of BizObj? It would work the same way as far as the order in which the constructors execute...

      Delete
  2. No, I mean that in your example you add (implemented) and form (UI-BAL-DAL)

    ReplyDelete
    Replies
    1. I still don't understand your question. But, let me try this:

      In my example, both the BAL and DAL are contained in one class, the BizObj class. That's not really the correct way to do this. If you're going to have a BAL, then the DAL should be a separate class (that gets instantiated in your BAL). But, that's not the point of the post ... I just thought I should clarify.

      Now, for your UI: Say that you have a AuthorForm. That Form would have a AuthorBizObj property or field (call it boAuthor or something similar). You could instantiate the boAuthor in either the AuthorForm's constructor or in the Load event-handler (and I think the Load would be better).

      Does this help?

      Delete
    2. Yes, I've understanded your anwser and how it work (best way).
      Thanks

      Delete
    3. You're welcome! I'm glad I could help! =0)

      Delete