You can override virtual methods. A simple example:
void Main()
{
A realA = new A();
A actuallyB = new B();
Console.WriteLine(realA.GetName()); // John
Console.WriteLine(actuallyB.GetName()); // Gillian
PrintName(realA); // John
PrintName(actuallyB); // Gillian
}
public void PrintName(A anyA)
{
Console.WriteLine(anyA.GetName());
}
public class A
{
public virtual string GetName()
{
return "John";
}
}
public class B : A
{
public override string GetName()
{
return "Gillian";
}
}
Your two classes can have different behaviour (within the bounds of Liskov Substitution Principle, of course), but the helper method PrintName
will work with both.
In fact, this is the whole reason for the existence of inheritance - you expose some useful interface, and everyone who's using it can treat it one way. If you want a more real world example, let's look at the Stream
class. For example, you might have a helper method that reads an image from a stream. Now, when you need to read an image from a file, you just pass a file stream to your helper method. When you want to read an image from a database, you just pass a database stream. When you want to read an image from a web server... As long as the streams conform to the stream interface (and the truth is, streams aren't exactly perfectly designed ;)), you can switch them at will, and everything will work as expected.