Tuesday, March 10, 2009

multilevel inheritance in C#

One of the important aspects of the Object Oriented Methodology is relationship. Objects do not exist as isolated entities, rather, they exhibit some kind of relationship with other objects. Some of the common relationships between the classes are listed below:-

Instantiation Relationship

This is the relationship that exists between a class and its instance or object. Real world examples of such a relationship can be:-

  • A Ferari is a Car
  • A Mobile Phone is a type of electronic device
1
2
3
4
5
6
7
8
9
10
11
class Car

{
string Model;
string Company;

string SerialNumber;
}

void Main(string[] args)

{
Car MyCar = new Car(); // Instantiation Relationship between MyCar & Car

}
Composition Relationship

Classes can be nested i.e a Class can contain another class. The relationship between two such classes is called composition relationship.

Composition

The following code represents the Composition relationship that is depicted in the above diagram.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Car
{
string SerialNumber;
string Model;

string Color;

class Engine
{

string Type;
string Model;

}

class Wheel
{
int Width;

string Manufacturer;
}
}
Utilization Relationship

The concept of OOP allows a class to make use of another class i.e delegate some portion of its work to another specialized class. The relationship between these two classes is termed as utilization. Ferari an object of the car class, is driven by Michael, an object of the driver class. These two entities have a utilization relationship between them.

The following code snippet demonstrates the utilization relationship between the Sorter and the Swapper class.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Sorter
{

public static void Sort(int[] A)

{
for (int I = 0; I < A.Length - 1; I++)

{
for (int J = I + 1; J < A.Length; J++)

{
if (A[I] > A[J])

{
// Utilizes the Swapper Class to do the swapping
Swapper.Swap(A[I], A[J]);

}
}
}
}

}

class Swapper
{
public static void Swap(ref int Num1, ref int Num2)

{
int Temp = Num1;
Num1 = Num2;

Num2 = Temp;
}
}

This example uses the bubble sort algorithm to sort an array of integers in the ascending order. While sorting, two elements of the list need to be swapped when they are not arranged ascendingly. The Sorter class employs the Swapper class for this job thus utilizing it.

Inheritance

Just as a child inherits qualities from his/her parents, a class can inherit data members and functions from another class. Consider the following class diagram:-

The Mammals class is the base class as it inherits its attributes to other classes. Dogs, cats & Humans are its child classes. This hierarchy is derived from the common set of attributes that the classes share. Mammals, for example are warm blooded, vertebrates, possess external ears and have hair on their body. These characteristics also pertain to Dogs, Cats, Humans, Lions, Tigers and Leopards, thus making them mammals. In C#, a class can have multiple child classes but only 1 base class. Multiple inheritance which existed in languages such as C++ has been scrapped because they tend to cause more problems than they solve.

Some key terms related to Inheritance are listed below.

  • Base(Super) Class - The class that inherits its properties to other classes.
  • Child(Sub) Class - The class that inherits its properties from other classes.
  • Multi-level Inheritance - A class which inherits from another class, serves as the base class for a third class. In the preeceding diagram, Lions, Tigers & Leopards are derived from the Cats class which itself is derived from the Mammals class. This is called multi-level inheritance.
  • Generalization - Classes that inherit from the same base class have certain common attributes which have been inherited from the common base class. This relationship is called Generalization.
  • Specialization - It refers to the uncommon characteristics of a sub class, those that make it different from others. When we say that Human is a kind of Mammal, we imply that they have the common properties of Mammals along with some specialized characteristics that make them different from other Mammals - They walk on two legs. Specialization is the opposite of Generalization.
Implementing Inheritance


1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
namespace ConsoleApplication1
{

class Program
{
static void Main(string[] args)

{
Cars MyFerari = new Cars();

MyFerari.NumberOfWheels = 4;
MyFerari.Drive();

}
}

public class Vehicles

{
private string Name;
public int NumberOfWheels;

public void Drive()
{

}
}

public class Cars : Vehicles

{

}
}

In this example, the Cars class is a sub class which is derived from the Vehicles class. The Cars class inherits the data member NumberOfWheels and the member function - Drive() from the Vehicles class. So, the MyFerari object of the Car class has access to these members.

Note: Private members are not accessible from the sub class. So, the follwoing code would cause a ConsoleApplication1.Vehicles.Name’ is inaccessible due to its protection level. error.

MyFerari.Name = "Ferari";
Determining Inheritance Hierarchies

This process is very simple as the only thing one needs to remember is that the sub class should be a type of the base class. For example: Human is a type of Mammal, Car is a type of vehicle and so on.

Note: Improper usage of Inheritance will not result in any syntactical error. But, the design model for the program would be at fault.

Constructor Inovking Order

Constructors being unique to a class are not inherited. Whenever an object of a child class is created, the constructor of both the parent and the child class is invoked. The parent class must come into existence before its child class can. Therefore, the constructor of the base class is invoked first followed by the constructor of the derived class. The destructors are invoked in the opposite order - derived to base. This is because the child class must be destroyed before the parent class.

The following program confirms these two order.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;


namespace ConsoleApplication1
{
class Program
{

static void Main(string[] args)

{
Cars MyFerari = new Cars();

Console.ReadLine();
}

}

public class Vehicles
{

public Vehicles()
{
Console.WriteLine("Vehicles -> Constructor Invoked");

}

~Vehicles()
{

Console.WriteLine("Vehicles -> Destructor Invoked");

}
}

public class Cars : Vehicles

{
public Cars()
{

Console.WriteLine("Cars -> Constructor Invoked");

}

~Cars()
{
Console.WriteLine("Cars -> Destructor Invoked");

}
}
}

Abstract Class

Consider the term Vehicle. It does not have an existence of its own. However, types of vehicles; namely, Car, Aeroplane, Bus, etc do. Similarly, we can have Abstract classes which cannot be instantiated thus exhibiting the abstract behavior. They merely contain the skeleton of the class but not its implementation. The abstract keyword is used to declare such a class.

1
2
3
4
5
6
7
8
9
10
abstract class Vehicle


{

}

static void Main(string[] args)

{
// Abstract Class cannot be instantiated
Vehicle obj = new Vehicle(); // Shows Compilation Error.

}
- Show quoted text -

One of the important aspects of the Object Oriented Methodology is relationship. Objects do not exist as isolated entities, rather, they exhibit some kind of relationship with other objects. Some of the common relationships between the classes are listed below:-

Instantiation Relationship

This is the relationship that exists between a class and its instance or object. Real world examples of such a relationship can be:-

  • A Ferari is a Car
  • A Mobile Phone is a type of electronic device
1
2
3
4
5
6
7
8
9
10
11
class Car

{
string Model;
string Company;

string SerialNumber;
}

void Main(string[] args)

{
Car MyCar = new Car(); // Instantiation Relationship between MyCar & Car

}
Composition Relationship

Classes can be nested i.e a Class can contain another class. The relationship between two such classes is called composition relationship.

Composition

The following code represents the Composition relationship that is depicted in the above diagram.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Car

{
string SerialNumber;
string Model;

string Color;

class Engine
{

string Type;
string Model;

}

class Wheel
{
int Width;

string Manufacturer;
}
}
Utilization Relationship

The concept of OOP allows a class to make use of another class i.e delegate some portion of its work to another specialized class. The relationship between these two classes is termed as utilization. Ferari an object of the car class, is driven by Michael, an object of the driver class. These two entities have a utilization relationship between them.

The following code snippet demonstrates the utilization relationship between the Sorter and the Swapper class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

class Sorter
{
public static void Sort(int[] A)

{
for (int I = 0; I < A.Length - 1; I++)

{
for (int J = I + 1; J < A.Length; J++)

{
if (A[I] > A[J])

{
// Utilizes the Swapper Class to do the swapping
Swapper.Swap(A[I], A[J]);

}
}
}
}

}

class Swapper
{
public static void Swap(ref int Num1, ref int Num2)

{
int Temp = Num1;
Num1 = Num2;

Num2 = Temp;
}
}

This example uses the bubble sort algorithm to sort an array of integers in the ascending order. While sorting, two elements of the list need to be swapped when they are not arranged ascendingly. The Sorter class employs the Swapper class for this job thus utilizing it.

Inheritance

Just as a child inherits qualities from his/her parents, a class can inherit data members and functions from another class. Consider the following class diagram:-

The Mammals class is the base class as it inherits its attributes to other classes. Dogs, cats & Humans are its child classes. This hierarchy is derived from the common set of attributes that the classes share. Mammals, for example are warm blooded, vertebrates, possess external ears and have hair on their body. These characteristics also pertain to Dogs, Cats, Humans, Lions, Tigers and Leopards, thus making them mammals. In C#, a class can have multiple child classes but only 1 base class. Multiple inheritance which existed in languages such as C++ has been scrapped because they tend to cause more problems than they solve.

Some key terms related to Inheritance are listed below.

  • Base(Super) Class - The class that inherits its properties to other classes.
  • Child(Sub) Class - The class that inherits its properties from other classes.
  • Multi-level Inheritance - A class which inherits from another class, serves as the base class for a third class. In the preeceding diagram, Lions, Tigers & Leopards are derived from the Cats class which itself is derived from the Mammals class. This is called multi-level inheritance.
  • Generalization - Classes that inherit from the same base class have certain common attributes which have been inherited from the common base class. This relationship is called Generalization.
  • Specialization - It refers to the uncommon characteristics of a sub class, those that make it different from others. When we say that Human is a kind of Mammal, we imply that they have the common properties of Mammals along with some specialized characteristics that make them different from other Mammals - They walk on two legs. Specialization is the opposite of Generalization.
Implementing Inheritance


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace ConsoleApplication1
{
class Program

{
static void Main(string[] args)

{
Cars MyFerari = new Cars();

MyFerari.NumberOfWheels = 4;
MyFerari.Drive();

}
}

public class Vehicles

{
private string Name;
public int NumberOfWheels;

public void Drive()
{

}
}

public class Cars : Vehicles

{

}
}

In this example, the Cars class is a sub class which is derived from the Vehicles class. The Cars class inherits the data member NumberOfWheels and the member function - Drive() from the Vehicles class. So, the MyFerari object of the Car class has access to these members.

Note: Private members are not accessible from the sub class. So, the follwoing code would cause a ConsoleApplication1.Vehicles.Name’ is inaccessible due to its protection level. error.

MyFerari.Name = "Ferari";
Determining Inheritance Hierarchies

This process is very simple as the only thing one needs to remember is that the sub class should be a type of the base class. For example: Human is a type of Mammal, Car is a type of vehicle and so on.

Note: Improper usage of Inheritance will not result in any syntactical error. But, the design model for the program would be at fault.

Constructor Inovking Order

Constructors being unique to a class are not inherited. Whenever an object of a child class is created, the constructor of both the parent and the child class is invoked. The parent class must come into existence before its child class can. Therefore, the constructor of the base class is invoked first followed by the constructor of the derived class. The destructors are invoked in the opposite order - derived to base. This is because the child class must be destroyed before the parent class.

The following program confirms these two order.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
using System;


namespace ConsoleApplication1
{
class Program
{

static void Main(string[] args)

{
Cars MyFerari = new Cars();

Console.ReadLine();
}

}

public class Vehicles
{

public Vehicles()
{
Console.WriteLine("Vehicles -> Constructor Invoked");

}

~Vehicles()
{

Console.WriteLine("Vehicles -> Destructor Invoked");

}
}

public class Cars : Vehicles

{
public Cars()
{

Console.WriteLine("Cars -> Constructor Invoked");

}

~Cars()
{
Console.WriteLine("Cars -> Destructor Invoked");

}
}
}


Abstract Methods

Abstract methods contain the function signature and return type, but no body. A child class can override the abstract method thus providing its implementation. Abstract methods are also declared by using the abstract keyword.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
abstract class Vehicle
{
public abstract void Run();

}

class Car : Vehicle
{
public override void Run()

{
Console.WriteLine("Run the Car");

}
}

class Bus : Vehicle
{

public override void Run()

{
Console.WriteLine("Run the Bus");

}
}

In this example, the abstract method Run() is declared in the Vehicle class. Notice the lack of the { } braces which marks the lack of a body. Since the Vehicle class cannot be instantiated, it does not need to have an implementation for the Run() method. The actual implementation is contained in its derived classes - Car, Bus. Thus, the abstract class only forms the skeleton of the child classes which exhibit specialization by overriding and implementing the abstract methods.

Note: Abstract methods can only be defined inside an abstract class.

Overriding Methods

In the previous example the override keyword is used. A parent class method can be overridden by a child class. In this way it provides its own implementation shadowing the one of the base class. A method must be declared as abstract or virtual to be overridden inside the child class.

Virtual Functions

The difference between a virtual function/method and an abstract method is that while the latter does not provide an implementation, the former does. If a virtual function of the parent class is not overridden, the method is inherited as it is, inside the child class. Again, we use the virtual keyword for declaring virtual functions.

The following example shows various cases when a method can/cannot be overridden.

- Show quoted text -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
abstract class Vehicle

{
// Abstract Method. Contains no body.
public abstract void Run();

}

class Car : Vehicle
{
// Abstract method is overridden.

public override void Run()

{
Console.WriteLine("Run the Car");

}

// Normal Method. Cannot be overridden.
public void Brake()

{
Console.WriteLine("Stop the Car");

}

// Virtual Method. Can be overridden.
public virtual void Accelerate()

{
Console.WriteLine("Step on the gas");

}
}

class BMW : Car
{

// An overridden method can be further overridden.
public override void Run()

{
Console.WriteLine("Run the BMW");

}

// Shows Compilation Error.
// The Brake method of Car is

// not declared as virtual or abstract.
public override void Brake()

{
Console.WriteLine("Stop the Car");

}

// Virtual method is overridden.
public override void Accelerate()

{
Console.WriteLine("Step on the gas");

}
}

From the following you can deduce that for a method to be overridden, it must be declared as abstract or virtual. An overridden method can be further overridden because it carries over the virtual modifier.

Sealed Classes

So many ways to modify a class but none to protect? Fear not, sealed classes are here to the rescue. This modifier prevents a class from being tampered by not allowing other classes to inherit from it.

1
2
3
4
5
6
7
8
9
10
sealed class Ferari

{

}

// Shows Error. Cannot inherit from sealed class.

class McLaren : Ferari
{

}
Sealed Methods

Use the sealed modifier to prevent a method from being overridden. Normally, you do not need to use this modifier as the methods are not overridable by default. However, if you want to protect an overridden method from being further overridden, you should use the sealed method instead of sealing off the entire class.

Interfaces

Remember that C# does not support multiple inheritance? Multiple inheritance tends to cause more problems than it solves. However, the ability to derive methods and properties from multiple sources is present in C#. This is done using Interfaces. Interfaces only contain the declaration part of a class. The actual definition which comprises of the body of the method is present inside the class which implements the interface.

Declaring Interfaces

They are declared similar to how classes are. Only differences are that they can only contain methods and properties (no variables), they do not contain the definition for these methods/properties and off-course the interface keyword.

interface Flyer
{
public void Fly();

}
Implementing Interfaces

Classes do not inherit from interfaces, rather implement them. Although, the process of doing this is the same.

class Aeroplane : Flyer
{


}

Multiple interfaces can be implemented as follows:-

class Aeroplane : Flyer, Vehicle
{


}

Here, Vehicle is also assumed to be an interface.

A class can inherit from another class and implement an interface in a similar fashion:-

class Bird : Mammal, Flyer
{


}

Note: Mammal is a class here.

Inheriting Interfaces

Interfaces themselves can inherit from other interfaces. Again, the process is the same.

interface MechanicalFlyer : Flyer
{


}
Why use interfaces?

Interfaces provide the skeletal structure of the classes which implement them. They separate the definition of objects from their implementation.

Why not just use Abstract classes?

Abstract classes are meant to be used when you want only some of the methods/properties to be implemented by the sub class. Besides, a class cannot inherit from multiple classes but it can implement multiple interfaces.

The following example depicts the need for interfaces.

- Show quoted text -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
abstract class Animal
{
public void Eat()

{
}
}

abstract class Vehicle
{

public void Run()
{

}
}

interface Flyer
{
public void Fly();

}

class Aeroplane : Vehicle, Flyer
{


}

class Bird : Animal, Flyer
{


}

As you can see, the two sub classes Bird and Aeroplane derive from the Animal and Vehicle classes respectively. Both have the characteristics of their respective base classes. The Bird like any other animal, eats while the Aeroplane being a vehicle, runs. However, they both share a common trait - the ability to fly. This ability is neither possessed by all animals nor by all vehicles. So it cannot be defined in either of the base classes. Again, it is not only possessed by the Aeroplane and Bird, some insects, baloons and other types of vehicles such as the Helicopter also possess it. It wouldn’t be effective to define this ability in each of them. Actually, it will be defined individually in each of these classes because each have their own way of flying, the bird flaps the wings, whereas the helicopter roatates its through a mechanical engine. However, this ability is declared in the Flyer interface so that any class which implements this interface would have to define the Fly() method by overriding it.