KnowDotNet

Inheritance and Implements Keywords

Make Inherited Classes Have Characteristics Of Implementing Classes

by Les Smith

I may get criticized or correceted by an object oriented guru, but a thought occurred to me while building a new application this week that I thought that I would pass along.  I am constantly looking for ways to keep from reinventing the wheel and making reusability of code a reality and not a pipedream that many talk about and don't do.  What they really do is copy, cut, and paste, creating many copies of the same code spread all over the place.  

Maybe someone has thought of this and done it, but I don't remember reading about it.  That could also be because someone did think about it, found it to be a bad idea, and dropped it.  The application that I was working on this week required me to inherit from a fairly involved base class.  However, this new application required new methods to be added to the base class so that I could get the desired functionality I needed from it.

I started adding some new
Overridable methods in the base class.  Most of them do nothing in the base class.  They are Subs in VB.NET, but in the new derived class that I was building they would obviously be used.  This particular base class processes through a batch of database transactions.  It normally calls a Web Service for each transaction and already had a couple of overridable methods that allow the derived class to change some properties just before the base class builds XML to send to the Web Service.

In the new derived class, I found that I needed to know when the batch is being started, when it is completed, and even allowed to make a decision as to whether to call the Web Service with a particular transaction.  This is where the following Overridable methods come into existence.

      ' Control comes here when the batch is set up for processing but
      ' before the first transaction has been read
      Protected Overridable Sub BeginBatch(ByVal Account As String, _
        
ByVal batchID As Integer)

      
End Sub

     ' Control passes here when the base class has completed the processing
     ' of all transactions in the batch.
     Protected Overridable Sub FinishedBatch(ByVal Account As String, _
        
ByVal batchID As Integer, ByVal errCount As Integer)

      
End Sub

      ' always return true to create a case, this method may be
      ' overriden in the derived class and possibly bypass the case.
      Protected Overridable Function CreateJob(ByVal dr As DataRow) As Boolean
         Return True
      End Function

      
     ' Control passes here when the base class has received word from the Web Service
     ' has created a new Job
      Protected Overridable Sub NewJob(ByVal caseID As String, ByVal dr As DataRow)

      
End Sub

In the derived class, I will use the methods to do things when the processing of the batch starts and finishes.  For example, I am going to open a results file at the beginning of the transaction processing.  When the NewJob method is called, I will write to the results file.  When the FinishedBatch method is called, I will close the results file and probably archive it and send it to the desired destination; maybe an FTP site.

With the processing of every transaction, I want to be able to query the database before the Web Service is called and may make the decision, based on the results of the query, not to process the transaction through the Web Service at all.  In that case, I will return False in the CreateJob method.

Now, I will address the thought behind this article.  If I write an
Interface class, every Public or Protected Member of the interface must be implemented in any class which Implements the Interface.   The presence of the Implements keyword in the implementing class will guarantee that you do not get a clean compile until all exposed members are implementd, and that's a good thing.  It means that the developer does not get the opportunity to forget to implement an exposed member frorm the Interface. Likewise, in a base class, all MustOverride Members must be overridden; otherwise the compiler will complain that you are missing a member from the base class that must be overriden in the derived class.

Here is the thought that I had, good or bad.  What if instead of delcaring members, especially methods as
Overridable in the base class, you declared them as MustOverride?  What you would effectively do is have the base class take on the characteristics of an Interface in that the compiler would guarantee that you are aware of all of the functionality available to you in the base class.  In other words, the compiler would not allow you to be ignorant of functionality that you could use, leaving you to try to kludge something because you were not aware that the base class provided that functionality.

There are a couple of obvious downsides in this proposal.  First, you would have to implement unwanted members in your derived class.  However, in VB.NET 2005, the compiler automatically stubs these members for you by the presence of the
MustOverride keyword in the base class.  If you do not wish to use the functionality, and assuming that the methods were Subs (returning void), you would not have to add any code to them and would thereby cause you no extra trouble.  However, by the fact that the compiler created the stub methods for you, you would always know all of the functionalality available to you.  In fact, you might determine that you could effectively use this functionality that you would not even know was in the base class were they simply coded as Overridable instead of MustOverride.

Perhaps the more serious downside is that if the base class is in use in other applications at the time that you add new
MustOverride members, you will now get compiler errors the next time that you compile those applications.  Worse yet, if the base class is in a DLL and a new copy of the DLL is placed in the GAC so that existing applications begin to use it, you will get broken applications at run-time.  That's a show stopper for this idea.  

For the two reasons I just described, this may not be such a good idea in base classes that have been around for a while.  If you are designing a new base class, it might be an option for making sure that a developer that inherits the class is made aware of all functionality even if they have not read the documentation to see all that is available and normally somewhat hidden due to the use of the
Overridable keyword.  Just a thought that intrigued me and I thought I would pass it along.  After all, it costs you nothing to consider it.

Ask a Question, or give your feedback on my articles or products by going to the KnowDotNet Forum or by clicking on My Blog.