OOP: Classic Inheritance and Polymorphism in C#

This post is based on Chapter 5+6 of Andrew Troelsen’s “Pro C# 2008 and the .Net Platform” available from Apress.

Note: for interfaces see a later article covering chapter 9.

Inheritance

Aa mentioned in a previous post, we have two general OOP methods of code reuse, the is-a and has-a relationship between objects. In the following let’s look into the is-a, or inheritance relationship a bit more.

So the basics here is that you define base classes, and any protected members are inherited in an deriving classes. Note that C# does not allow multiple inheritance – but, it does allow classes and structs to implement multiple interfaces, which means that you really have no need for multiple inheritance. More on this later on.

Sometimes you might find that you want to stop all futher inheritance from a certain class (this is often applicable to utility classes where inheritance is senseless) – in such cases you can (and I guess it’s recommended that you do) use the sealed keyword, like this:

	public sealed class EmailUtilities
	{ }

Note also that structs are sealed by definition (implicitly).

Constructors in Inheriting Classes

By default, the base class default constructor will be executed before any logic in your inheriting class’ constructor. Note that if you have a base class with a constructor that takes say three arguments, and you inherit from this class, your derived class will not by default have access to this constructor.
Because of this it is good practice (and will often make a lot of sense) to use the base keyword to forward arguments onto the base constructor. So you will do stuff like this:

	public class DerivedClass : BaseClass
	{
		public DerivedClass(string str, int x) : base(str, x)
		{
			//Code here will execute AFTER the base class constructor logic
		}
	}

Containment/Delegation

This is the black art of exposing one object from another, also known as a “has-a” relationship, as opposed to the “is-a” that we know (and love) from classic inheritance.

So what’s the point? Well, there is a lot of point to it. Once you get into designing your own class hierarchies (and do btw make sure you use the VS visual class designer tool for this, but always make sure you understand the generated code as well) you will find that it makes a lot of sense. Orders have OrderLines, Employees have Addresses etc etc. Really this is a very important part of OOP implementation, but it’s also one that you will find quite logical.

However, one important question is how do you actually do this in the best and most consistent way? Do you simply expose the entire object – or do you write local methods that utilise the object behind the scenes? So, for example, say we have an Employee and let’s just for the sake of illustration say that an Employee can only have one Address object. Should we then write a method called UpdateEmployeeUpdate in the Employee class – and within this update and save the contained Address object – or, should we place an UpdateAddress method on the Address object, and simply expose the Address object directly as a property of the Employee…?

The answer is: It’s up to you!! But fret not, or at least don’t fret completely, we will revisit this later in the upcoming OO Design Patterns series. For now, know and understand that we are once more looking at responsibility – and personally I like placing this as close to home as possible, so in the above I would indeed place this at the Address and never write any logic in the Employee that deals directly with updating address details.

Yet another alternative, a kinda soft middle ground, is to expose the UpdateEmployeeAddress method, but simply pass the params straight through to the Address object – however this to me just muddles the waters, and makes it unclear who is responsible for what.

Anyways – as I said we will return to these happy deliberations, for now, let’s focus on the mechanics – let’s look at the possible, not the advisable, if I may be so lyric (bloody late here I’m telling ya, falling asleep as a I type).

Yet another option for the has-a relationship is nested types. This is types defined within another type, so for example a class within a class or an enum or struct within a class.

Some implications of this:

  • You can declare these as private – and hence limit the access to the containing class.
  • The nested class is a member of the containing class, and as such has access to all members (incl private) of the parent class.
  • The nesting can be as deep (i.e. as many levels) as you require.

So this is not inheritance, but clearly a has-a, that gives you some interestin options. Generally, you will use this to define utility classes that are only used by the containing class. If this is not what you need, you should as a rule define an independant class and implement your has-a relationship using one of the aforementioned techniques.

Polymorphism

So as mentioned in a previous post Polymorphism is a process that allows us to treat a bunch of related object in a consistent manner – effectively delegating the responsibility for implementing the requested action into each respective class definition (so really we are looking at another layer of encapsulation).
So an (overused) example could be the abstract concept of an Employee which forms the basis for an inheritance tree of different types of Employees – each of which you can tell to CalculateHoliday(); because the Employee object stipulates that all inheriting classes are able to handle this method.

So, how does the Employee class achieve this? Well – there are two options, the Employee class can either define CalculateHoliday() as an abstract method or a virtual method.
Virtual methods are basically a default behaviour, which inheriting classes are free to override (using just that keyword). In contrast an abstract method is just an empty method definition, which inheriting methods are required to override. Note that a class must be defined as abstract in order to contain abstract methods or properties – but that an abstract class can contain both abstract, virtual and “normal” members.

So, basically you would use abstract classes for concept that are too …well, abstract for it to make any sense to ever instantiate an object of this type. For example you might have a type called Product. Now, while there are a list of methods and properties that we can imagine all products should have, it generally speaking does not make sense to work with a Product object.

So, to recap – we can give Product some protected or public properties that will be applied to all kinds of Products via classic inheritance, we can have some virtual methods or properties that provide a default implementation of a certain functionality, but can be overridden in inheriting classes – and finally we can define some abstract methodsor properties, which have no implementation and must be overriden in inheriting classes.

When overriding virtual or abstract members, note that you can use the base keyword to call the base method you are overriding, and that you should always do this if you are reusing the logic from here (so if you are extending and not replacing – as will often be the case).

Also, make sure you use VS200x nice little shortcuts for this type of thing, just type override, and you will see a list of possible members , select one and hit enter, and your method stub is there.

Note also that you can seal a virtual method at any level in the inheritance chain by using of course the sealed keyword – so you mark the method as “override sealed” – and this means that thie method cannot be overridden again further down the inheritance chain (so your sealed override becomes the final implementation of that method).

A “polymorphic interface” refers to all the abstract and virtual methods and properties of an abstract class.

Member Shadowing

A not really related, but kinda similar topic – is member shadowing. This is when a derived class defines a member that is identical (by name and signature) to an inherited member. This is not illegal, but will give you a compiler warning, which should give you a clue that it’s not best practise.
However, you might sometimes want to do this intentionally. Say if for instance you are inheriting from a 3rd party assembly (or any other “no code access” scenario) – and you want to change some behaviour, you can then hide the inherited member like this – and use the new keyword to get rid of your compiler warning. So basically just define your member (be it field, property or method) with the new keyword in front the definition.

Casting Object

So a few notes on casting, which you will find yourself using a lot when working with polymorphic class hierarchies.

First of all, it’s always safe to cast downwards, and you can work with this anyway you want. However if you are casting upwards (so you have a derived class object in a base class type reference) you must do this explicitly using the (type) method.

Note that you can also use the is keyword to check for types – but really, this would be indicative of some missed polymorphic opportunity (you can imagine some nightmarish if/else statement doing different things depending on the actual type).

If you need to do type checking, always try and use the as keyword, this returns null if the case was not successful and allows you to use a simple if(myRef != null) check afterwards (it’s the best casting practise – use it!).

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: