Introduction
This little article is intended for rank .NET newbies who are making their
first attempts at C# programming. I assume that they have done some elementary
C++ programming and know what classes and member functions are. Using a few
simple code snippets we'll see how C# supports inheritance and polymorphism.
Inheritance & Polymorphism
When you derive a class from a base class, the derived class will inherit all
members of the base class except constructors, though whether the derived class would be able to
access those members would depend upon the accessibility of those members in the
base class. C# gives us polymorphism through inheritance. Inheritance-based
polymorphism allows us to define methods in a base class and override them with
derived class implementations. Thus if you have a base class object that might
be holding one of several derived class objects, polymorphism when properly used
allows you to call a method that will work differently according to the type of
derived class the object belongs to.
Consider the following class which we'll use as a base class.
class Animal
{
public Animal()
{
Console.WriteLine("Animal constructor");
}
public void Greet()
{
Console.WriteLine("Animal says Hello");
}
public void Talk()
{
Console.WriteLine("Animal talk");
}
public virtual void Sing()
{
Console.WriteLine("Animal song");
}
};
Now see how we derive another class from this base class.
class Dog : Animal
{
public Dog()
{
Console.WriteLine("Dog constructor");
}
public new void Talk()
{
Console.WriteLine("Dog talk");
}
public override void Sing()
{
Console.WriteLine("Dog song");
}
};
Now try this code out.
Animal a1 = new Animal();
a1.Talk();
a1.Sing();
a1.Greet();
Animal constructor
Animal talk
Animal song
Animal says Hello
Okay, that came out just as expected. Now try this code out.
Animal a2 = new Dog();
a2.Talk();
a2.Sing();
a2.Greet();
Animal constructor
Dog constructor
Animal talk
Dog song
Animal says Hello
We have an object of type Animal
, but it references an object of type
Dog
.
Thus you can see the base class constructor getting called first followed by the
derived class constructor. Now we call Talk()
and find that the method that's
executed is the base class method. That's not surprising when you consider that
the object was declared to be of the base type which in our case is Animal
. Now
when we call Sing()
, we find that the derived class method has got called. This
is because in the base class the method is prototyped as public virtual void
Sing()
and in the derived class we have overridden it by using public override void Sing()
.
In C#, we need to explicitly use the override
keyword as opposed to
C++ where we didn't have to do that. And finally when we call Greet()
the base class method gets called and this is not confusing at all
specially since the derived class has not even implemented the method.
Now try the following code out.
Dog d1 = new Dog();
d1.Talk();
d1.Sing();
d1.Greet();
Animal constructor
Dog constructor
Dog talk
Dog song
Animal says Hello
Okay, here everything came out as expected. No rude surprises there. The fact
that we could invoke the Greet()
method is proof of inheritance in
C#, not that anyone had any doubts to begin with I guess. Now take a look at
this new class we'll be using as a base class for some other classes.
class Color
{
public virtual void Fill()
{
Console.WriteLine("Fill me up with color");
}
public void Fill(string s)
{
Console.WriteLine("Fill me up with {0}",s);
}
};
Now run this code out.
Color c1 = new Color();
c1.Fill();
c1.Fill("red");
Fill me up with color
Fill me up with red
Okay, that went fine, I'd say. Now let's derive a class from this class.
class Green : Color
{
public override void Fill()
{
Console.WriteLine("Fill me up with green");
}
};
Now let's try this code out.
Green g1 = new Green();
g1.Fill();
g1.Fill("violet");
Fill me up with green
Fill me up with violet
Well, that went fine too. Thus if you have overloaded methods, you can mark
some of them as virtual
and override them in the derived class. It's not
required that you have to override all the overloads. Now I want to demonstrate
some stuff on overloaded constructors. For that we'll use the following base
class.
class Software
{
public Software()
{
m_x = 100;
}
public Software(int y)
{
m_x = y;
}
protected int m_x;
};
Now we'll derive a class from the above class.
class MicrosoftSoftware : Software
{
public MicrosoftSoftware()
{
Console.WriteLine(m_x);
}
};
Now try this code out
MicrosoftSoftware m1 = new MicrosoftSoftware();
100
The base class had two overloaded constructors. One that took zero arguments
and one that took an int
. In the derived class we only have the zero argument
constructor. Constructors are not inherited by derived classes. Thus we cannot
instantiate a derived class object using the constructor that takes an int
as
parameter. As you will deduce from the output we got, the base class constructor
that called was the default parameter-less constructor. Now take a look at this
second derived class.
class DundasSoftware : Software
{
public DundasSoftware(int y) : base(y)
{
Console.WriteLine(m_x);
}
public DundasSoftware(string s, int f) : this(f)
{
Console.WriteLine(s);
}
};
Here we have two constructors, one that takes an int
and one
that takes a string
and an int
. Now lets try some code
out.
DundasSoftware du1 = new DundasSoftware(50);
50
DundasSoftware du2 = new DundasSoftware("test",75);
75
test
There, now that you've seen how it came out, things are a lot clearer I bet.
You can use the this
and base
access keywords on other
methods too, and not just on constructors.
Conclusion
This article does not discuss interfaces. At least not in it's current
version. I'll probably add the usage of interfaces in the next update. But for
now, I recommend that you read up on interfaces from elsewhere.
History
- 09 Jul 2002 - Article redone completely, sample project added.
- 10 Oct 2001 - Article posted [My first article on CP]