|Deep C# - Inheritance|
|Written by MIke James|
|Wednesday, 11 November 2020|
Page 1 of 4
Inheritance is a simple idea, until you try to make use of it. What's a virtual method? How do you use override and new? Its tricky when you look at the details.
This is Chapter 4 of our ebook on C# - a work in progress.
Inheritance is an idea that beginners take a long time to understand properly and even when they do there is a lot of scope for making mistakes.
C#’s inheritance mechanisms are particularly clean and easy but let’s make sure that we know how they work.
The fundamental class declaration in C# takes the form:
If you don’t specify a base class then the default class called “object” is used.
Only a class can inherit and only from another class – structs always inherit from “object” and can’t be used to create new structs or classes by inheritance. If you want to create a class that can’t be used as a base class for a new class then simply add the “sealed” modifier to the start of the class definition.
Notice that C# only allows single inheritance which is by contrast to C++ and something of a relief!
If you think that C++’s ability to create classes from more than one base class is a good idea then you haven’t seen some of the stranger things that can happen when this powerful facility gets out of hand.
The prefered approach to multiple inheritance like features is to make use of interfaces which define the type of what is to be inherited without supplying an implementation.
There is no doubt that single inheritance is safer and can do everything that multiple inheritance can if you are prepared to approach it in the right way.
When you create an instance of a class you first create a reference variable of the correct type. For example:
doesn’t create an instance of A; only a reference variable capable of pointing to an object of type A – you have to be careful how you phrase such ‘pointing to an object’ because C# doesn’t have pointers as such but we all know what is going on here!
After declaring a reference variable you can set it to point to or reference a new instance of the class using:
Of course you can put both parts together to read:
Which has a tendency to confuse beginners because of the repeated use of the class name A. The first gives the type of MyA and the second creates an instance of A.
If you now create a class that inherits from A:
Then any instance of B starts out with all of the methods defined in the definition of A. This is what inheritance is all about - code reuse. If class A has a show method then so now does class B and without you having to write a single line of code.
Notice that this means that class B has two types of method - those that are defined as part of A and those that are defined within it.
If you simply want to use the inherited methods of class B you can simply use them as if they were "native" to B.
results in the show method defined in class A being called.
There is one small complication - what if the methods of class B need to call the methods defined in class A?
One of the advantages of single inheritance is that if you want to call the base class’s methods you can do so with a single keyword “base” because you don't have to specify which base class is to be used as there is only one.
For example, if B inherits a method “show” from A then B can call the method using:
In practice you can omit "base" as long as there is no ambiguity i.e. if B doesn't have a show method.
A special case of using the base classes methods is the inherited constructor.
If a class inherits from another class then the base class default constructor is automatically called before the child class’s own constructor. If the base class also inherits from another class its constructor is called first and so on until we reach the first class in the inheritance chain.
If a class defines an explicit constructor and inherits from another class the explicit constructor must call one of the base class’s constructors. If the base class only has constructors that use parameters the child class has to call one of them using the “base” keyword.
For example suppose Class1 has a constructor of the form MyClass1(int n) then to call it you would write:
In this case the MyClass2 constructor calls the MyClass1(int n) constructor as MyClass(7) before continuing with its own instructions.
Notice that the “this” keyword can nearly always be used to make clear that the version of something to be used is the class’s own version and “base” can be used to indicate that the possibly hidden base class’s version should be used. In most cases you don't have to use this and base because the compiler can work out what you mean but it is a good idea to be explicit whenever clarity warrents it.
|Last Updated ( Thursday, 11 February 2021 )|