The Second Pillar of Object-Oriented Programming - Inheritance
Introduction:
Inheritance provides the ability to build a new class based on an existing class. It allows you to extend a base class by enabling a new class to inherit its characteristics and behavior.
The greatest thing about inheritance is code reuseability. If you have a class that has some functionality (characteristics and behavior) and you want to create another class that has the same functionality but with some new characteristics and behaviors then instead of creating an entirely new class that has the same code you have previously created then all you need to do is to create the new class and add to it only the new characteristics and behavior and inherit the rest from the old class.
The base class
The base class is a normal class that has characteristics (variables) and behaviors (methods) that are common to all subclasses.
Example:
public class Car
{
string model;
int currentSpeed;
int maxSpeed;
public Car()
{ }
public Car(string model, int currentSpeed, int maxSpeed)
{
this.model = model;
this.currentSpeed = currentSpeed;
this.maxSpeed = maxSpeed;
}
public string Model
{
get { return model; }
set { model = value; }
}
public int CurrentSpeed
{
get { return currentSpeed; }
set { currentSpeed = value; }
}
public int MaxSpeed
{
get { return maxSpeed; }
set { maxSpeed = value; }
}
}
As you can see, the car class has characteristics that any car of each type can have so it has the general variables that are common for any car.
The Subclass (derived class)
The subclass is a class that inherits its core functionality from a base class then it add its own functionality
Example:
public class BMW : Car
{
}
We left our BMW class without adding any variables or methods so the BMW class is the same as the Car class so if you tried to use it you will see that it has all the characteristics of the Car class.
Example:
BMW bmw1 = new BMW();
bmw1.Model = "X5";
bmw1.CurrentSpeed = 0;
bmw1.MaxSpeed = 230;
So let us see how to extend our Car type by adding some functionality to its child BMW.
Creating the subclass:
As I said, all you need to do with your subclass is to add the new functionality to it and it will inherit all the common functionality from the base class.
Example:
public class BMW : Car
{
bool isFullOption;
bool hasDVD;
public BMW()
{ }
public BMW(string model, int currentSpeed, int maxSpeed, bool isFullOption, bool hasDVD)
{
//using the BMW class variables
this.isFullOption = isFullOption;
this.hasDVD = hasDVD;
//using the CAR class properties
Model = model;
CurrentSpeed = currentSpeed;
MaxSpeed = maxSpeed;
}
}
As you saw, we create the BMW subclass and add two other variables to it (isFullOption, hasDVD) and we created a custom constructor and use it to assign the value of the BMW class variables and the properties inherited from the base class Car.
Using the base class constructors:
Instead of creating a custom constructor in the subclass that has the same code in the base class constructor, we can create a constructor that calls the base class constructor and use the subclass constructor to assign values to the variables that belongs to the subclass.
Example:
public class BMW : Car
{
bool isFullOption;
bool hasDVD;
public BMW()
{ }
public BMW(bool isFullOption, bool hasDVD, string model, int currentSpeed, int maxSpeed)
: base(model, currentSpeed, maxSpeed)
{
//using the BMW class variables
this.isFullOption = isFullOption;
this.hasDVD = hasDVD;
}
}
We here create a custom constructor in the subclass and we will use it to receive values from the object user, like isFullOption, hasDVD, model, currentSpeed, and maxSpeed and then we assigned the isFullOption and hasDVD values in the subclass constructor and pass the model, currentSpeed, and maxSpeed values to the base class constructor.
BMW bmw1 = new BMW(true, true, "X5", 100, 230);
The first two parameters will be used by the subclass constructor and the last three will be used by the base class constructor.
Allowing the subclass to see the base class variables (the protected keyword):
As you saw previously, all the base class members are private so the subclass cannot see it and can only deal with it by its properties, so if we want the subclasses to see the variables of the base class then we need to redefine these variables as protected.
public class Car
{
protected string model;
protected int currentSpeed;
protected int maxSpeed;
public Car()
{ }
public Car(string model, int currentSpeed, int maxSpeed)
{
this.model = model;
this.currentSpeed = currentSpeed;
this.maxSpeed = maxSpeed;
}
}
The protected keyword means that the base class variables are accessible only by the subclasses and private to all other classes.
By using protected members we created a level of trust between the base and derived classes.
We now can use the Car class variables directly in the BMW subclass without using any properties.
public class BMW : Car
{
bool isFullOption;
bool hasDVD;
public BMW()
{
//we now can use the member of the base class
currentSpeed = 0;
maxSpeed = 230;
}
public BMW(bool isFullOption, bool hasDVD, string model, int currentSpeed, int maxSpeed)
: base(model, currentSpeed, maxSpeed)
{
//using the BMW class variables
this.isFullOption = isFullOption;
this.hasDVD = hasDVD;
}
}
The sealed classes
We can create classes that cannot be inherited using sealed keywords in the class definition, so if we tried to inherit from a sealed class then we will have a compile-time error.
Example:
We can define our BMW class as a sealed class as in the following:
public sealed class BMW : Car
{
bool isFullOption;
bool hasDVD;
public BMW()
{
//we now can use the member of the base class
currentSpeed = 0;
maxSpeed = 230;
}
public BMW(bool isFullOption, bool hasDVD, string model, int currentSpeed, int maxSpeed)
: base(model, currentSpeed, maxSpeed)
{
//using the BMW class variables
this.isFullOption = isFullOption;
this.hasDVD = hasDVD;
}
}
If we tried to inherit from the BMW class then we will have a compile-time error.
//Compile time error
public class MiniCoper : BMW
{
}
Note: C# dose not allow multiple base classes, so classes can inherit only from one base class.