Object-Oriented Programming in C# .NET - Part 4






4.36/5 (11 votes)
A look at advanced concepts such as inheritance, polymorphism, sealed classes and partial classes in C#
Introduction
Now that you know the basics of classes and related concepts, we will turn our face to more advanced things. In this part, we will cover the following:
- Inheritance
- Polymorphism
- Sealed classes
- Partial classes
What is Inheritance?
Inheritance is the fact that a class inherits the members of another class. Suppose we have created a SimpleMath
class that does four basic mathematical operations for us: Addition
, Subtraction
, Multiply
, Division
:
public class SimpleMath
{
public int Addition(int x, int y)
{
return x + y;
}
public int Subtraction(int x, int y)
{
return x – y;
}
public int Multiply(int x, int y)
{
return x * y;
}
public int Division(int x, int y)
{
return x / y;
}
}
Now, we want to have a more advanced math
class that does some additional operations besides these four basic ones. Now, instead of copying all of the above lines of code into our new Math
class, we make the new class derive from the first class. This way, we avoid copying code:
public class AdvancedMath:SimpleMath
{
public double ConvertDegreesToRadians(double degrees)
{
double radians = ( System.Math.PI / 180 ) * degrees;
return ( radians );
}
public double ConvertRadiansToDegrees(double radians)
{
double degrees = ( 180 / System.Math.PI ) * radians;
return ( degrees );
}
}
All of the public
and protected
members are inherited by the AdvancedMath
class. In general, we can just inherit the public
and protected
members. The two classes don’t need to be in the same file. We can make an inheritance hierarchy simply by identifying base classes and make more specific classes derive from them. The two classes work independently from each other.
Class Program
{
static void Main(string[] args)
{
SimpleMath sm = new SimpleMath ();
int result = sm.Addition ( 1, 3 );
Console.WriteLine (result );
AdvancedMath am = new AdvancedMath ();
double radian = am.ConvertDegreesToRadians ( 120 );
Console.WriteLine (radian);
Console.ReadKey ();
}
}
What is Polymorphism?
Polymorphism means ‘many forms’. It is implemented in various ways. One of them is by overloading. Overloading happens on methods. It means that a method does a specific job according to the parameter that the user provides. You can see a lot of method overloading in .NET. Most of the .NET built-in classes have overloaded constructors. It means that when you want to instantiate a class, you have the choice of providing different formats of input to the constructor and the class, automatically, runs the specific constructor according to your input. Just try to instantiate an object of type System.IO.FileStream
. It has up to 15 different overloads for its constructor:
FileStream fs = new FileStream ( “C:\\a.txt”, FileMode.Append );
FileStream fs2 = new FileStream ( “C:\\a.txt”, FileMode.Append, FileAccess.Read );
FileStream fs3 = new FileStream
( “C:\\a.txt”, FileMode.Append,FileAccess.Read ,FileShare.None,128);
Overloading is not limited to constructors. Any method can have overloads. The way to declare an overload is very simple. All of the overloads of a method have the same name but different parameters. Take a look at the following constructors within a Car
class assuming it has a Name
and NumberOfDoors
property:
public Car()
{
Name = “NoName”;
NumberOfDoors = 3;
}
public Car(string name, int numberOfDoors)
{
Name = name;
NumberOfDoors = numberOfDoors;
}
public Car(string name)
{
Name = name;
NumberOfDoors = 0;
}
public Car(int numberOfDoors)
{
Name = “”;
NumberOfDoors = numberOfDoors;
}
When we want to instantiate an object of type car
, according to our input one of the above constructors are called:
class Program
{
static void Main(string[] args)
{
Car c1 = new Car ();
Car c2 = new Car ( 3 );
Car c3 = new Car ( “MyName” );
Car c4 = new Car ( “MyName”, 4 );
Console.WriteLine (c1.NumberOfDoors );
Console.WriteLine (c1.Name );
Console.WriteLine ( c2.NumberOfDoors );
Console.WriteLine ( c2.Name );
Console.WriteLine ( c3.NumberOfDoors );
Console.WriteLine ( c3.Name );
Console.WriteLine ( c4.NumberOfDoors );
Console.WriteLine ( c4.Name );
Console.ReadKey ();
}
}
As shown, the four constructors are different in just their type of parameters. Now, let’s see how overloading on methods other than constructors works. Suppose we have a Math
class as follows:
class Math
{
public int Add(int x, int y)
{
return x + y;
}
public int Add(int x)
{
return x + 1;
}
public int Add(int x, int y, int z)
{
return x + y + z;
}
}
We instantiate a class of type Math
and call the four Add
methods as follows:
class Program
{
static void Main(string[] args)
{
Math m = new Math ();
int result = 0;
result = m.Add ( 2 );
Console.WriteLine (result );
result = m.Add ( 2, 3 );
Console.WriteLine (result );
result = m.Add ( 2, 4, 5 );
Console.WriteLine (result );
Console.ReadKey ();
}
}
That’s enough for now. We will look at other forms of polymorphism in the coming parts of this article. For now, let’s go to the next concept of this chapter: sealed classes.
What is a Sealed Class?
A sealed class is class that cannot be inherited. When you mark a class as sealed using the sealed
keyword, any attempts by the other classes to derive from it will fail:
public sealed class notDerivable
{
int f1;
public int F1
{
get { return f1; }
set { f1 = value; }
}
public int SomeMethod()
{
Console.WriteLine (“Some Method”);
}
}
public class FailingClass:notDerivable
{
}
Simply put, the final nodes in your class hierarchy are sealed
because you don’t want others to extend your final
classes. However, the middle nodes should not be sealed
in order to be extensible by other developers in need.
And now for the last part of this chapter, let’s learn about partial
classes.
What is a Partial Class?
Partial
classes are those that can be separated between two files. Suppose you want to create a immense class with lots of properties and methods. One option is to create it all in one class file. However, this makes the class file very crowded and hard to maintain. You had better split your class into two or more class files: creating properties in one file, methods in another and constructors in yet another one. To tell the compiler that all these files hold the definition of one single class, we put partial
keyword before the class
keyword in our class definition. The following is the code I have put in my ImmenseClassProperties class
file:
partial class ImmenseClass
{
private string stringField;
public string StringField
{
get { return stringField; }
set { stringField = value; }
}
private int intFiled;
public int IntFiled
{
get { return intFiled; }
set { intFiled = value; }
}
}
Now, the ImmenseClassMethods file:
partial class ImmenseClass
{
public void WriteStringField()
{
Console.WriteLine ( StringField );
}
public void WriteIntField()
{
Console.WriteLine ( IntFiled );
}
}
And ImmenseClassConstructor file:
partial class ImmenseClass
{
public ImmenseClass(string intFiled, string stringFiled)
{
IntFiled = intFiled;
StringField = stringField;
}
}
Note that all these class
files are within the same namespace
and all belong to ImmenseClass
. They differ only in the name of the class
file not the class
itself, if you get what I mean. Ok. Let’s close our discussion here. You will learn more in the next part of this article. Till then happy coding.
History
- 5th July, 2011: Initial version