Browse DevX
Sign up for e-mail newsletters from DevX


Inheritance 101 : Page 4

Extend your knowledge of inheritance to more easily extend your .NET applications.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Inheritance In Reality
Developing simulations is fun, they map well to the concepts of inheritance, and they're great for presentations because they are so visual. But most of us don't write simulation applications. In reality, most of us write business applications. That is when it gets easy to both use and abuse inheritance. Let's look at the abuse first. There are several situations where it may not make sense to use inheritance.

  • If all properties and methods in a base class are defined with MustOverride, then the base class provides no default functionality. In this case, you are better off using an interface. By using an interface, you also gain flexibility because you can define more than one interface on a class. Whereas you can only define one base class for a class. For example, if you want to ensure that all of your business objects (BO) have Retrieve, Validate, and Save methods, you can create a BO interface and implement that interface in each business object instead of creating a BO base class.
  • If the base class provides a set of general functions that are not semantically related to the child classes, then the base class is really a library and not a base class. For example, if you have a set of logging features that are used by all of your business objects, create a Logging class with shared methods and call the methods as needed from your business objects. This Logging class can then be part of a library that is reusable in other applications.
  • If the inheritance hierarchy is more than five classes deep, it becomes more difficult to manage the set of properties and methods provided by all of the class up the inheritance hierarchy. This can lead to errors and inappropriate behavior.
As an example of the last point, I spoke with a developer from Australia that implemented a deep hierarchy of classes for an army simulation program that he was writing. The simulation had many types of classes in the hierarchy to define different types of aircraft, vehicles, artillery, and individual troops. After the army reviewed the simulation, being Australia they thought it would be more realistic to add kangaroos to field. So one of the developers simply added another subclass on the deep hierarchy under the soldier class because it contained the functionality for initialization and movement. Wasn't he surprised when he ran the simulation and the kangaroos shot back! It is easy to forget to override all of the appropriate properties and methods when your hierarchy is too deep. To do inheritance well, you should first look at the entities involved with your application. Then define the commonalities among the classes along with their differences. From that point, you can define a semantically correct inheritance hierarchy and implement the appropriate classes for that hierarchy.

But this is often easier said than done. Agile development processes are very popular these days. This means that you most likely don't know all that your application will need to do when you start architecting and building the application. Rather, you begin with the features that you are implementing first, develop your code so that it is easy to maintain, then you later add features based on their defined priority. Using an agile approach, you don't always know all of the classes in your application. This makes it difficult to define the commonality between the classes. For this reason, you may find that your first implementation of your application may not have any inheritance relationships. As you continue to add and enhance classes over time, you will recognize the commonality between the classes. It is then that you will want to refactor the classes to use inheritance.

For example, let's say we are developing an invoicing application for a consulting company using an agile approach. The first iteration would include the basic invoicing features, such as the ability to generate an invoice based on each employee's time. The first iteration could define classes for Employee, Project, Timesheet, and Invoice.

The reality of software development does not always allow us to clearly create the inheritance hierarchy up front.
For the second iteration, the users defined the need for a pre-pay invoice. We find much commonality between the time-based invoice and pre-pay invoice, so we refactor the Invoice class creating a base Invoice class and two child classes for time-based and pre-pay.

For the third iteration, the users defined the need to bill for subcontracted labor as well. Again we refactor, this time creating a Person base class with Employee and Subcontractor child classes. The reality of software development does not always allow us to clearly create the inheritance hierarchy up front. Rather, inheritance relationships are often defined as the application is implemented and as it is enhanced and modified over time.

The important thing to remember about inheritance is that its entire purpose is to provide an easy way for your application to share similarities between classes while still preserving their differences.

Deborah Kurata is cofounder of InStep Technologies Inc., a professional consulting firm that focuses on turning your business vision into reality using Microsoft .NET technologies. She has over 15 years of experience in architecting, designing, and developing successful .NET applications. Deborah is the author of several books, including "Doing Objects in Visual Basic 6.0" (SAMS) and "Doing Web Development: Client-Side Techniques" (APress). She is on the INETA Speaker's Bureau and is a well-known speaker at technical conferences.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date