Saturday, April 14, 2012

virtual opens the door for override and there is a reason for you to care

If we have a class called Bird like so:

namespace Aviary.Core.Objects
{
   public class Bird
   {
      public Bird() {}
      public virtual string Speak()
      {
         return "Chirp!";
      }
   }
}

 
 

...and we had a class named Owl that inheirted from Bird like so that hid its Speak() method like so:

namespace Aviary.Core.Objects
{
   public class Owl : Bird
   {
      public Owl() {}
      public string Speak()
      {
         return "Who?";
      }
   }
}

 
 

C# 4.0 in a Nutshell, a book I am reading, suggests this is what might be called hiding a method. In this approach an Owl could ask "Who?" but if we upcast the Owl to a Bird the bird would lose the ability to ask "Who?" and would only chirp as seen here:

[TestMethod]
public void TestOwl()
{
   Owl owl = new Owl();
   Bird birdMadeFromOwl = owl;
   Assert.AreEqual(owl.Speak(),"Who?");
   Assert.AreEqual(birdMadeFromOwl.Speak(), "Chirp!");
}

 
 

I'll leave it to you to decide if this is a good thing or a bad thing, but I will offer that there is a way to keep this from happening by using the override keyword as seen here:

namespace Aviary.Core.Objects
{
   public class Parrot : Bird
   {
      public Parrot() {}
      public override string Speak()
      {
         return "Yo! What's up?";
      }
   }
}

 
 

Look at the difference:

[TestMethod]
public void TestParrot()
{
   Parrot parrot = new Parrot();
   Bird birdMadeFromParrot = parrot;
   Assert.AreEqual(parrot.Speak(), "Yo! What's up?");
   Assert.AreEqual(birdMadeFromParrot.Speak(), "Yo! What's up?");
}

 
 

Override lets our child's method survive the manhandling of an upcasting. The override word alone does not do the trick however. Without the virtual keyword at the Bird object at the top of this blog posting it would not have been possible. In the absence of the virtual keyword at a parent's method signature only the hiding approach is feasible.

No comments:

Post a Comment