After being in TFS-Land for a couple of months and celebrating the birth of my second daughter, I finally had time to go back to do some C# coding. Hurray!
Then, I ran into an interesting issue:
When you derive from a class which has an interface implemented you cannot just override the implement methods again. Even if you use the new keyword breaks when you cast the instance to the interface type, you might not achieve the desired result.
Let's look at a quick example and deal with solutions afterwards:
public interface ITom
{
string IdeaOfTheDay();
}
public class BaseClass : ITom
{
public string IdeaOfTheDay()
{
return "Base Idea";
}
}
public class DerivedClass : BaseClass
{
//I have to use the new keyword
public new string IdeaOfTheDay()
{
return "New Idea";
}
}
DerivedClass d = new DerivedClass();
Console.WriteLine(d.IdeaOfTheDay());
//Writes: New Idea
ITom t = d as ITom;
Console.WriteLine(t.IdeaOfTheDay());
//Writes: Base Idea -> oops not what I hoped for
Okay this shouldn't have come as a surprise to me. When I thought about it for a second, I realized it is standard polymorphism with contracting to a specific non virtual method. Using interfaces made me forget this for a second.
If we didn't have interaces and we could not change the BaseClass to virtual or make the BaseClass abstract, we would be done here. Even using the new keyword does not work if we cast to an interface, because the actual contract is with the BaseClass.
Pretty bad when you deal with customer dlls where you cannot modify the source code.
Cheating Polymorphism with Interfaces in an emergency
But with interfaces there is one more thing you can do if you can not change the BaseClass:
Just re-implement the Interface!
public class BaseClass : ITom
{
public string IdeaOfTheDay()
{
return "Base Idea";
}
}
public class DerivedClass : BaseClass, ITom
{
//We still need the keyword
public new string IdeaOfTheDay()
{
return "New Idea";
}
}
DerivedClass d =new DerivedClass();
Console.WriteLine(d.IdeaOfTheDay());
//Writes: New Idea
ITom t = das ITom;
Console.WriteLine(t.IdeaOfTheDay());
//Writes: New Idea NOT: Base Idea anymore
Kind of messy but this can be a lifesaver!
Using Polymorphism correctly with Interfaces
But if you can modify the BaseClass you definitely want to use virtual methods.
Even though Interfaces are not virtual by nature, you can still declare the method virtual in your class implementation and make them virtual!
This gives you the best out of both worlds: Polymorphism from Inheritance and Contracting via Interfaces.
public class BaseClass : ITom
{
public virtual string IdeaOfTheDay()
{
return "Base Idea";
}
}
public class DerivedClass : BaseClass{
//normal overriding
public override string IdeaOfTheDay()
{
return "New Idea";
}
}
DerivedClass d = new DerivedClass();
Console.WriteLine(d.IdeaOfTheDay());
//Writes: New Idea
ITom t = d as ITom;
Console.WriteLine(t.IdeaOfTheDay());
//Writes: New Idea NOT: Base Idea anymore
Think about it: An interace is just a contract! Nothing more, nothing less!
Tom