Inheritance by construction in VBA

There is no built in method for class inheritance in VBA – only interface inheritance (via implementing an interface).  Even if we could inherit from another class a general good programming rule is to prefer interface inheritance and use construction (and delegation) to achieve the behaviour we want in our classes … but what does this mean?

In this post we are going to cover this with examples in VBA.  Our starting point is the interface post here and we will use the same example of a car quotation system.  The general direction and goal is to construct a number of classes for cars by using other base classes for cars.  Throughout this post I will be a little loose with my terminology and use the term “derived class” to refer to any class that either directly inherits from a base class or a class that achieves the same thing from construction and delegation.

What do we mean by construction and delegation?

When using object oriented languages and programming techniques we usually have the ability for one class (the derived class) to inherit from another class (the base class).  When a derived class inherits from a base it automatically obtains certain member data fields and methods from the base class.  Below is an example from C# where the derived class automatically obtains all public member data and methods from the base class and has access to all protected data and methods.

One key benefit of inheritance is code re-use (we don’t have to duplicate code in the derived class).  We can also (in certain cases) override the base class methods and behaviour (though I try not to if possible). To achieve a similar functionality and structure in VBA we would have to duplicate a lot of code since we can’t inherit.

An alternative to inheritance is what we are aiming for here: construction and delegation.  Under this technique we would (at a high level):

  1. Construct our base class with the default data, methods etc;
  2. Construct a derived class and have this contain an object of the base class type;
  3. Within the derived class we provide methods to implement behaviour and allow these to call the same method on the object of type base class (i.e. we delegate);
  4. In this way we can decide which methods directly delegate and which methods (in the base class) have their own definition in the derived class;
  5. We can also add other methods/data that is not in the base class;

The above is more work than simply inheriting but allows for more loose coupling of classes and can achieve the same goal.  The loose coupling has some benefits on it’s own: your code becomes more robust to change and more flexible in general.

How we can achieve this while implementing interfaces in VBA

The UML diagram below shows the shape of how we are going to do the construction for our car quotation application.

DelegationClassDiagram

The general idea is that we have an interface that is implemented by all car classes.  In this way they have to provide the methods specified in the interface (the Property Get and Let methods and the HonkHorn method).  The base car class will provide most of the details for how each of these will be implemented and the member data to back them.  The other car classes will contain an object of the base class type and for most of the interface methods will delegate to the base object.  For the HonkHorn the Ford and Toyota cars will provide their own class level implementation of the method and for the interface implementation will delegate to this (rather than the base object).  They will also have their own constructors.

The below video talks about the general shape of how our classes are going to fit together for this example.

Base class construction

As a reminder the code for the interface we are using is given below.

For our base car class to implement this we use the following code which is very similar to our previous versions of CFordCar and CToyotaCar here.

The techniques we use to implement the interface are exactly the same as before: we delegate the interface implementations of the methods to a class version using “Me”.  The important changes for this post are in the next section when we construct the derived classes.

Derived class construction

The derived class is where we make the changes and do the work here.  Sometimes it can be tedious to implement these (compared to straight class inheritance) but we do avoid duplicating code.  Below I have included example code for the CFordCar class which implements the ICar interface by construction from a CBaseCar object.  Some of the key things to notice are:

  • In the CFordCar constructor we initialize the CBaseCar object – this makes sure we have the correct type for the object and avoids accidental null reference errors;
  • In the constructor we initialize values for the various CBaseCar object member data;
  • The only class method we have now in CFordCar is the HonkHorn method.  We delegate to this method (rather than the base object) in the interface implementation of HonkHorn;
  • All others directly implement the interface methods by delegating to the base object;

The below video talks through the example of building a derived class from a base class.

Extending a base class

If we are creating a derived class the reason for this may be that we want to re-use the code in a base class and then add a few more methods (e.g. a local extension).  This can be done in a similar way to the derived class construction we covered in the previous section – we add the additional methods to our derived class as class methods and make sure we provide class methods for all base class methods that delegate to a base object.  The key thing to keep in mind is:

  • When we declare an object of an interface type only the interface methods will be available;
  • To obtain the additional methods we need to declare the object of the derived type;

As an example consider the CPorscheCar class defined below.  This includes a new class method RevEngine but doesn’t provide class implementations of all the get and let methods (they are provided at the interface implementation level only).

I wouldn’t call the CPorscheCar an extension of the base car since we haven’t provided all property get and set methods at a class level (so can’t access them) but if we did provide class level implementations (that delegate to the base object) then it would be an extension and able to implement the interface.

We can demonstrate what is available to various objects using the following subroutine in a normal code module.

All of the videos from this post can be downloaded from here.

The example spreadsheet including the code above (and code for the userform) can be downloaded using the button below.

Inheritance by construction example spreadsheet

Errata

I would like to say a big thank you to Steven Bohlken for pointing out a few typos in the code and an unhandled run-time error in the code.  As I result I have updated the code listings and the example download file.  I have yet to update the videos but will do in the fullness of time.  A list of specific fixes are given below.  Thanks a lot Steve!

  1. In the quotation userform there was a typo in a  With ... End With block which led to a new form being created and used on the fly (instead of the one already created and initialised).  While not a big problem the code is much cleaner after fixing this;
  2. The userform contained an unhandled error when an invalid car was chosen and the user clicked “Get Quote” (since the code tries to honk the horn of an invalid car).  To fix this I included what I call a “soft” user input validation on the combo box selection change event and on the “Get Quote” click event;
  3. A number of class module member data variables were declared using  Dim instead of  Private – it is good coding practise to explicitly set all member data to private and this is what I have now done;

3 thoughts on “Inheritance by construction in VBA

  1. I feel like a REAL programmer, now that I know how to extend a class using Implementation and Delegating in VBA.
    Making this knowledge available is indeed a service to the IT community and it is very much appreciated.

    • You are welcome David – glad you like the post. I have been a little busy over the past few months so haven’t had a lot of time to put up new posts. Hopefully this will change soon and I have a lot of ideas for new content (just a case of finding the time!). Paul.

Leave a Reply

Your email address will not be published. Required fields are marked *